Datenstrukturen - fbi.h

Werbung
1
18
Datenstrukturen
 2006 Pearson Education, Inc. All rights reserved.
2
18.1 Einführung
18.2 Selbstbezügliche Klassen
18.3 Dynamische Speicherzuweisung und
Datenstrukturen
18.4 Verkettete Listen
18.5 Stapel
18.6 Warteschlangen
18.7 Bäume
 2006 Pearson Education, Inc. All rights reserved.
3
18.1 Einführung
• Container-Klassen (oder Collection-Klassen)
– Klassen, die dafür entworfen sind, eine Ansammlung von
Objekten zu enthalten
– Stellen üblicherweise Dienste wie Einfügen, Entfernen,
Kopieren, Suchen, Sortieren, usw. zur Verfügung
– Beispiele
• Arrays
• Stacks
• Queues
• Verkettete Listen
• Bäume
 2006 Pearson Education, Inc. All rights reserved.
4
18.1 Einführung
• Dynamische Datenstrukturen für Container
– Wachsen und schrumpfen während der Programmausführung
– Verkettete Liste (‘List’)
• Ansammlung von Daten, die in einer Reihe hintereinander
angeordnet sind
• Einfügen und Entfernen ist an jeder Stelle möglich
– Stapel (‘Stack’)
• Einfügen und Entfernen nur an einer Stelle (Oben, ‘Top’)
• LIFO (last in, first out)
– Warteschlange (‘Queue’)
• Einfügen am Ende (‘Back’), Entfernen am Anfang (‘Front’)
• FIFO (first in, first out)
 2006 Pearson Education, Inc. All rights reserved.
5
18.1 Einführung
• Dynamische Datenstrukturen für Container
– Binärbaum (‘Binary Tree’)
• Ansammlung von Daten, in der jedes Element maximal zwei
direkte Nachfolger hat
• Erleichtert
– Schnelles Suchen und Sortieren
– Entfernen von Duplikaten
• Eingesetzt für
– Verzeichnisse von Dateisystemen
– Compiler
– Assoziative Arrays (STL)
 2006 Pearson Education, Inc. All rights reserved.
6
18.2 Selbstbezügliche Klassen
• Selbstbezügliche Klasse
– Enthält einen Zeiger als Datenelement, der auf ein Objekt
desselben Klassentyps zeigt
– Beispiel
• class Node
{
…
Node* nextPtr;
};
– Zeiger nextPtr ist ein Verbindungsglied (‘Link’)
• Kann einen Knoten (‘Node’) mit einem anderen
Knoten verbinden
 2006 Pearson Education, Inc. All rights reserved.
7
Fig. 18.1 | Zwei miteinander verbundene Objekte einer selbstbezüglichen Klasse.
 2006 Pearson Education, Inc. All rights reserved.
8
Häufiger Programmierfehler
Wird der Link im letzten Knoten einer
verketteten Datenstruktur nicht auf den
Nullzeiger (nullptr) gesetzt, resultiert ein
(möglicherweise ernster) logischer Fehler.
 2006 Pearson Education, Inc. All rights reserved.
18.3 Dynamische Speicherzuweisung
und Datenstrukturen
9
•new Operator
–
–
–
–
Weist dynamisch Speicher für ein Objekt zu
Übernimmt den Typ des Objekts als Argument
Gibt die Speicheradresse des neuen Objekts zurück
Beispiel
• Node* newPtr = new Node( 10 );
– Reserviert sizeof( Node ) Bytes für ein neues NodeObjekt
– Ruft den Node Konstruktor mit dem Argument 10 auf
– Weist die Adresse des neuen Node-Objekts newPtr zu
 2006 Pearson Education, Inc. All rights reserved.
18.3 Dynamische Speicherzuweisung
und Datenstrukturen
10
•delete Operator
– Ruft den Destruktor für ein Objekt auf und gibt den
entsprechenden Speicher frei.
– Beispiel
• delete newPtr;
– Ruft den Node Destruktor für das Objekt, auf das
newPtr zeigt, auf
– Gibt den Speicher für das Objekt, auf das newPtr
zeigt, frei
– Entfernt die Zeigervariable newPtr nicht
– Wird delete für einen Nullzeiger aufgerufen, hat dies
keinen Effekt.
 2006 Pearson Education, Inc. All rights reserved.
11
18.4 Verkettete Listen
• Verkettete Liste
– Lineare Sequenz von selbstbezüglichen Klassenobjekten
• Die einzelnen Objekte werden ‘Knoten’ genannt.
• Sie sind durch Links (d.h. Zeiger) miteinander verbunden.
– Auf die Liste wird über einen Zeiger auf den ersten
Knoten zugegriffen.
• Auf die folgenden Knoten wird jeweils über den Link des
Vorgängerknotens zugegriffen.
– Der Link im letzten Knoten wird üblicherweise auf den
Nullzeiger (nullptr) gesetzt.
– Zusätzliche Knoten werden bei Bedarf dynamisch erzeugt.
 2006 Pearson Education, Inc. All rights reserved.
12
18.4 Verkettete Listen
• Verkettete Liste
– Vorteile gegenüber Arrays
• Verkettete Listen sind dynamisch.
– Die Länge kann genau dem Bedarf angepasst werden.
• Neue Elemente können effektiv in eine sortierte Liste
eingefügt werden.
– Die vorhandenen Listenelemente müssen nicht bewegt
werden.
– Nachteil gegenüber Arrays
• Der direkte Zugriff auf ein Listenelement ist nicht möglich.
– Die Liste muss immer vom Anfang bis zum gewünschten
Element durchgegangen werden.
 2006 Pearson Education, Inc. All rights reserved.
13
Tipp zur Performanz
Einfügen in und Entfernen eines Elements aus
einem sortierten Array kann sehr zeitaufwändig
sein - alle Elemente, die auf das eingefügte oder
entfernte Element folgen, müssen entsprechend
verschoben werden (O(n): linearer Zeitaufwand).
Eine verkettete Liste erlaubt effizientes Einfügen
und Entfernen überall in der Liste
(O(1): konstanter Zeitaufwand).
 2006 Pearson Education, Inc. All rights reserved.
14
Tipp zur Performanz
Auf ein Arrayelement kann direkt zugegriffen
werden, da die Adresse jedes Elements direkt
aufgrund seiner Position relativ zum Arrayanfang
berechnet werden kann (O(1): konstanter
Zeitaufwand).
Bei einer verketteten Liste kann jedes Element nur
über das Durchlaufen aller Vorgängerelemente
erreicht werden (O(n): linearer Zeitaufwand).
 2006 Pearson Education, Inc. All rights reserved.
15
Betrachtung zum Software Engineering
Die Auswahl einer Datenstruktur hängt
üblicherweise von der Performanz bestimmter
Operationen ab, die von einem Programm
verwendet werden, und von der Ordnung, in
der die Daten in der Datenstruktur gehalten
werden.
Beispielsweise ist es in der Regel effizienter, ein
Element in eine sortierte verkettete Liste
einzufügen als in ein sortiertes Array.
 2006 Pearson Education, Inc. All rights reserved.
16
Fig. 18.2 | Graphische Darstellung einer Liste.
 2006 Pearson Education, Inc. All rights reserved.
17
Tipp zur Fehlervermeidung
Dem Link (Zeigerelement) eines neuen Knoten
sollte immer der Nullzeiger (nullptr)
zugewiesen werden.
Zeiger sollten initialisiert werden, bevor sie
verwendet werden.
 2006 Pearson Education, Inc. All rights reserved.
1
// Fig. 18.3: Listnode.h
2
// Template ListNode class definition.
3
#ifndef LISTNODE_H
4
#define LISTNODE_H
Outline
18
5
6
// forward declaration of class List required to announce that class
7
// List exists so it can be used in the friend declaration at line 13
8
template< typename NODETYPE > class List;
Listnode.h
(1 von 1)
9
10 template< typename NODETYPE>
11 class ListNode
12 {
13
friend class List< NODETYPE >; // make List a friend
14 public:
15
ListNode( const NODETYPE & info ) : data( info ), nextPtr( nullptr ) { }
16
NODETYPE getData() const { return data; }
17 private:
18
NODETYPE data;
19
ListNode * nextPtr; // next node in list
data speichert einen Wert
vom Typ NODETYPE
20 }; // end class ListNode
21
22 #endif
nextPtr speichert einen Zeiger auf das nächste
ListNode Objekt in der verketteten Liste
 2006 Pearson Education,
Inc. All rights reserved.
1
2
3
// Fig. 18.4: List.h
// Template List class definition.
#ifndef LIST_H
4
5
6
#define LIST_H
7
8
9
#include <sstream>
#include <string>
#include "listnode.h" // ListNode class definition
Outline
#include <iostream>
19
List.h
(1 von 7)
10
11 template< typename NODETYPE >
12 class List
13 {
14 public:
15
List(); // constructor
16
17
18
~List(); // destructor
List( const List& ) = delete; // no copies of List-Objects allowed
const List& operator=( const List& ) = delete; // no assignment allowed
19
20
21
void insertAtFront( const NODETYPE & );
void insertAtBack( const NODETYPE & );
bool removeFromFront( NODETYPE & );
22
23
24
bool removeFromBack( NODETYPE & );
void insertInOrder( const NODETYPE & );
bool isEmpty() const;
firstPtr zeigt auf den ersten ListNode in
der List und lastPtr auf den letzten
25
std::string toString() const;
26 private:
27
ListNode< NODETYPE > * firstPtr; // pointer to first node
28
ListNode< NODETYPE > * lastPtr; // pointer to last node
29 }; // end class List
30
 2006 Pearson Education,
Inc. All rights reserved.
31
32 // default constructor
33 template< typename NODETYPE >
Outline
34 List< NODETYPE >::List()
35
: firstPtr( nullptr ), lastPtr( nullptr )
36 {
37
// empty body
38 } // end List constructor
39
Beide Zeiger mit Nullzeiger
initialisieren
20
List.h
(2 von 7)
40 // destructor
41 template< typename NODETYPE >
42 List< NODETYPE >::~List()
43 {
44
45
if( !isEmpty() ) { // List is not empty
46
47
48
std::cerr << "Destroying nodes ...\n";
49
50
51
ListNode< NODETYPE > *tempPtr;
52
53
54
55
56
57
ListNode< NODETYPE > *currentPtr = firstPtr;
while( currentPtr != nullptr ) { // delete remaining nodes
tempPtr = currentPtr;
std::cerr << tempPtr->data << '\n';
currentPtr = currentPtr->nextPtr;
delete tempPtr;
} // end while
} // end if
Alle ListNode Objekte im List
Objekt müssen freigegeben werden,
wenn das List Objekt zerstört wird
58
59
std::cerr << "All nodes destroyed\n\n";
60 } // end List destructor
61
 2006 Pearson Education,
Inc. All rights reserved.
21
Fig. 18.4a | Graphische Darstellung der Operation insertAtFront.
 2006 Pearson Education, Inc. All rights reserved.
22
Fig. 18.4b | Graphische Darstellung der Operation insertAtBack.
 2006 Pearson Education, Inc. All rights reserved.
62
Outline
63 // insert node at front of list
64 template< typename NODETYPE >
Neuer ListNode, der value
als Datenelement enthält
65 void List< NODETYPE >::insertAtFront( const NODETYPE & value )
66 {
67
ListNode< NODETYPE > * newPtr = new ListNode< NODETYPE >( value );
68
69
if( isEmpty() ) // List is empty
70
firstPtr = lastPtr = newPtr; // new list has only one node
71
else // List is not empty
72
{
73
newPtr->nextPtr = firstPtr; // point new node to previous 1st
74
firstPtr = newPtr; // aim firstPtr at new node
75
} // end else
76 } // end function insertAtFront
77
78 // insert node at back of list
79 template< typename NODETYPE >
23
List.h
(3 von 7)
Für eine leere Liste werden
firstPtr und lastPtr
node auf newPtr gesetzt
‘Einfädeln’ des neuen Knotens in die Liste, so dass
der neue Knoten auf den alten ersten Knoten
zeigt und firstPtr auf den neuen Knoten
80 void List< NODETYPE >::insertAtBack( const NODETYPE & value )
81 {
82
ListNode< NODETYPE > * newPtr = new ListNode< NODETYPE >( value );
83
84
if( isEmpty() ) // List is empty
85
firstPtr = lastPtr = newPtr; // new list has only one node
86
else // List is not empty
87
{
88
lastPtr->nextPtr = newPtr; // update previous last node
89
lastPtr = newPtr; // new last node
90
} // end else
91 } // end function insertAtBack
‘Einfädeln’ des neuen Knotens in die Liste,
so dass der alte letzte Knoten auf den
 2006 Pearson Education,
neuen Knoten zeigt und lastPtr auch
Inc. All rights reserved.
24
Fig. 18.4c | Graphische Darstellung der Operation Operation removeFromFront.
 2006 Pearson Education, Inc. All rights reserved.
92
Outline
93 // delete node from front of list
94 template< typename NODETYPE >
95 bool List< NODETYPE >::removeFromFront( NODETYPE & value )
96 {
97
98
List.h
return false; // delete unsuccessful
} // end if
100
else {
101
Entfernt den ersten Knoten aus der
Liste und kopiert den Wert des
Knotens in den Referenzparameter
if( isEmpty() ) { // List is empty
99
Ein zweiter Zeiger auf den ersten Knoten,
(4 von 7)
der für das Löschen gebraucht wird
ListNode< NODETYPE > * tempPtr = firstPtr; // hold tempPtr to delete
102
103
104
105
106
firstPtr = lastPtr = nullptr; // no nodes remain after removal
else
firstPtr = firstPtr->nextPtr; // point to previous 2nd node
108
value = tempPtr->data; // return data being removed
109
delete tempPtr; // reclaim previous front node
110
return true; // delete successful
} // end else
112 } // end function removeFromFront
113
Eine Liste mit nur einem Element
ist nach dem Entfernen leer
if ( firstPtr == lastPtr ) // List has one element
107
111
25
firstPtr zeigt jetzt auf
den zweiten Knoten (den
neuen ersten Knoten)
Der Datenwert des entfernten Knotens
wird in den Referenzparameter
value kopiert
Der Speicherplatz des entfernten
Knotens wird freigegeben
 2006 Pearson Education,
Inc. All rights reserved.
26
Fig. 18.4d | Graphische Darstellung der Operation Operation removeFromBack.
 2006 Pearson Education, Inc. All rights reserved.
114 // delete node from back of list
115 template< typename NODETYPE >
116 bool List< NODETYPE >::removeFromBack( NODETYPE & value )
117 {
118
119
if( isEmpty() ) { // List is empty
return false; // delete unsuccessful
120
} // end outer if
121
else {
122
Outline
Entfernt den letzten Knoten
aus der
Liste und kopiert den Wert des
Knotens in den Referenzparameter
27
List.h
ListNode< NODETYPE > * tempPtr = lastPtr; // hold
Ein zweiter Zeiger auf den letzten Knoten,
(5 von 7)
tempPtrder
to für
delete
das Löschen gebraucht wird
123
124
125
if( firstPtr == lastPtr ) { // List has one element
126
} // end inner if
127
else {
128
wird die Adresse
des ersten Knotens als
Startwert für das Durchlaufen
der Liste zugewiesen
firstPtr = lastPtr = nullptr; // no nodes remain after removal
currentPtr
ListNode< NODETYPE > * currentPtr = firstPtr;
129
130
// locate second-to-last element
131
while( currentPtr->nextPtr != lastPtr )
132
Durch die Liste laufen, bis currentPtr
auf den vorletzten Knoten zeigt, der der
neue letzte Knoten wird
currentPtr = currentPtr->nextPtr; // move to next node
133
134
lastPtr = currentPtr; // remove last node
135
currentPtr->nextPtr = nullptr; // this is now the last node
currentPtr wird der neue letzte Knoten
136
137
} // end inner else
138
value = tempPtr->data; // return value from old last node
139
delete tempPtr; // reclaim former last node
140
return true; // delete successful
141
} // end outer else
144 } // end function removeFromBack
143
Der Datenwert des entfernten Knotens wird in
den Referenzparameter value kopiert
Der Speicherplatz des entfernten Knotens wird freigegeben
 2006 Pearson Education,
Inc. All rights reserved.
145// insert node in sorted order
146 template< typename NODETYPE >
147 void List< NODETYPE >::insertInOrder( const NODETYPE & value )
Fügt einen Knoten in sortierter
Outline
Reihenfolge in die Liste ein
28
148 {
149
150
if( isEmpty() ) { // List is empty
firstPtr = lastPtr = = new ListNode< NODETYPE >( value );
151
} // end if
152
else {
153
if(
154
Für eine leere Liste werden firstPtr und lastPtr auf den neuen ListNode gesetzt.
(6 von 7)
!(firstPtr->data < value) ) { // same as: firstPtr->data >= value
insertAtFront( value ); // value is the new first element
155
} // end else if
156
else if ( lastPtr->data < value ) {
157
insertAtBack( value ); // value is the new last element
158
} // end else if
159
else {
160
List.h
Der neue Knoten kommt an den
Anfang bzw. das Ende der Liste.
ListNode< NODETYPE > * currentPtr = firstPtr->nextPtr,
161
162
* previousPtr = firstPtr,
Durch
* newPtr = new ListNode< NODETYPE >( value );
163
// locate element in front of and behind new node
164
while( currentPtr != lastPtr && currentPtr->data < value ) {
165
previousPtr = currentPtr;
166
currentPtr = currentPtr->nextPtr; // move to next node
167
} // end while
168
previousPtr->nextPtr = newPtr; // newPtr gets linked between
169
newPtr->nextPtr = currentPtr;
170
171
die Liste laufen, bis
currentPtr->data
nicht mehr kleiner als
value ist
// previousPtr and currentPtr
} // end inner else
} // end outer else
172 } // end function insertInOrder
Der neue Knoten wird zwischen previousPtr
und currentPtr eingehängt.
173
 2006 Pearson Education,
Inc. All rights reserved.
174 // is List empty?
Outline
175 template< typename NODETYPE >
176 bool List< NODETYPE >::isEmpty() const
29
177 {
178
return firstPtr == nullptr;
List.h
179 } // end function isEmpty
180
(7 von 7)
181 // returns contents of List as a string
182 template< typename NODETYPE >
183 std::string List< NODETYPE >::toString() const
184 {
185
std::stringstream outStream;
186
if( isEmpty() ) { // List is empty
187
outStream << "The list is empty\n\n";
188
} // end if
189
else {
Durch die Liste iterieren und den
Datenwert jedes Knotens ausgeben
190
ListNode< NODETYPE > *currentPtr = firstPtr;
191
outStream << "The list is:\n";
192
while( currentPtr != nullptr ) { // get element data
193
outStream << ' ' << currentPtr->data;
194
195
currentPtr = currentPtr->nextPtr;
} // end while
196
outStream << "\n\n";
197
} // end else
198
return outStream.str();
199 } // end function toString
200
201 #endif
 2006 Pearson Education,
Inc. All rights reserved.
1
// Fig. 18.5: fig18_05.cpp
2
// List class test program.
3
#include <iostream>
4
#include <string>
5
using namespace std;
6
7
#include "List.h" // List class definition
8
#include "Employee.h" // Employee class as defined in Kapitel 11 (fig11_05)
9
Outline
30
fig18_05.cpp
(1 von 6)
10 // function to test a List
11 template< typename T >
12 void testList( List< T > & listObject, const string & typeName )
13 {
14
cout << "Testing a List of " << typeName << " values\n";
15
cout << "Enter one of the following:\n"
16
<< "
1 to insert at beginning of list\n"
17
18
<< "
<< "
2 to insert at end of list\n"
3 to delete from beginning of list\n"
19
<< "
4 to delete from end of list\n"
20
<< "
5 to insert an element in sorted order\n"
21
<< "
6 to end list processing\n";
22
23
int choice; // store user choice
24
T value; // store input value
25
26
do { // perform user-selected actions
27
cout << "? ";
28
cin >> choice;
 2006 Pearson Education,
Inc. All rights reserved.
29
30
31
switch( choice ) {
case 1: // insert at beginning
32
cout << "Enter " << typeName << ": "; cin >> value;
33
34
listObject.insertAtFront( value );
break;
35
case 2: // insert at end
36
cout << "Enter " << typeName << ": "; cin >> value;
37
listObject.insertAtBack( value );
38
break;
39
40
41
42
43
44
45
46
47
Outline
31
fig18_05.cpp
(2 von 6)
case 3: // remove from beginning
if( listObject.removeFromFront( value ) )
cout << value << " removed from list\n";
break;
case 4: // remove from end
if( listObject.removeFromBack( value ) )
cout << value << " removed from list\n";
break;
case 5: // insert in order
48
cout << "Enter " << typeName << ": "; cin >> value;
49
listObject.insertInOrder( value );
50
break;
51
} // end switch
52
cout << listObject.toString();
53
54
} while( choice != 6 ); // end do...while
55
cout << "End list test\n\n";
56 } // end function testList
 2006 Pearson Education,
Inc. All rights reserved.
57
58 int main()
59 {
Outline
60
// test List of int values
61
List< int > integerList;
62
testList( integerList, "integer" );
fig18_05.cpp
64
// test List of Employee values
65
List< Employee > EmployeeList;
(3 von 6)
66
testList( EmployeeList, "Employee" );
63
32
67 } // end main
 2006 Pearson Education,
Inc. All rights reserved.
Testing a List of integer values
Enter one of the following:
1 to insert at beginning of list
2 to insert at end of list
3 to delete from beginning of list
4 to delete from end of list
5 to insert an element in sorted order
6 to end list processing
? 1
Enter integer: 1
The list is:
1
Outline
33
fig18_05.cpp
(4 von 6)
? 1
Enter integer: 2
The list is:
2 1
? 2
Enter integer: 3
The list is:
2 1 3
? 3
2 removed from list
The list is:
1 3
? 3
1 removed from list
The list is:
3
 2006 Pearson Education,
Inc. All rights reserved.
? 4
3 removed from list
The list is empty
? 6
End list test
Testing a List of Employee values
Enter one of the following:
1 to insert at beginning of list
2 to insert at end of list
3 to delete from beginning of list
4 to delete from end of list
5 to insert an element in sorted order
6 to end list processing
? 5
Enter Employee: Builder, Bob
The list is:
Builder, Bob
Outline
34
fig18_05.cpp
(5 von 6)
? 5
Enter Employee: Doe, John
The list is:
Builder, Bob
Doe, John
? 5
Enter Employee: Builder, Alice
The list is:
Builder, Alice
Builder, Bob
Doe, John
 2006 Pearson Education,
Inc. All rights reserved.
? 5
Enter Employee: Doe, Jack
The list is:
Builder, Alice
Builder, Bob
Doe, Jack
Doe, John
? 6
The list is:
Builder, Alice
Builder, Bob
Doe, Jack
Doe, John
Outline
35
fig18_05.cpp
(6 von 6)
End list test
Destroying nodes ...
Builder, Alice
Builder, Bob
Doe, Jack
Doe, John
All nodes destroyed
All nodes destroyed
 2006 Pearson Education,
Inc. All rights reserved.
36
18.4 Verkettete Listen
• Weitere Typen von verketteten Listen
– Zirkuläre, einfach verkettete Liste
• Zeiger im letzten Knoten zeigt zurück auf den ersten Knoten
– Doppelt verkettete Liste
• Jeder Knoten hat einen Link auf den nächsten Knoten und einen
Link auf den vorausgegangenen Knoten
• Zwei “Anfangszeiger”
– Einen auf den ersten Knoten, einen auf den letzten Knoten
• Erlaubt Durchläufe sowohl vorwärts als auch rückwärts
– Zirkuläre, doppelt verkettete Liste
• Vorwärtslink auf den letzten Knoten zeigt auf den ersten Knoten
• Rückwärtslink auf den ersten Knoten zeigt auf den letzten Knoten
 2006 Pearson Education, Inc. All rights reserved.
37
Fig. 18.6 | Zirkuläre, einfach verkettete Liste.
 2006 Pearson Education, Inc. All rights reserved.
38
Fig. 18.7 | Doppelt verkettete Liste.
 2006 Pearson Education, Inc. All rights reserved.
39
Fig. 18.8 | Zirkuläre, doppelt verkettete Liste.
 2006 Pearson Education, Inc. All rights reserved.
40
18.5 Stapel
• Stapel (Stack)
– Knoten können nur ‘von oben’ (top) hinzugefügt und
entfernt werden (LIFO: last-in, first-out)
– Kann als eingeschränkte verkettete Liste implementiert
werden
• Link des letzten Knotens eines Stapels wird auf den Nullzeiger
gesetzt (und bleibt auch immer der Nullzeiger), um den Boden
des Stapels zu kennzeichnen
– Erlaubte Operationen: Elementfunktionen push und pop
• push fügt einen neuen Knoten oben auf dem Stapel hinzu
• pop entfernt den obersten Knoten des Stapels und gibt seinen
Wert zurück
 2006 Pearson Education, Inc. All rights reserved.
41
18.5 Stapel
• Stapel (Stack)
– Realisierung in zwei Varianten
• private Vererbung
• Komposition
– In beiden Fällen wird die öffentliche Schnittstelle der
zugrunde liegenden Liste verborgen, indem nur noch
privater Zugriff darauf erlaubt wird, und eine neue
öffentliche Schnittstelle mit der Funktionalität eines
Stack realisiert.
 2006 Pearson Education, Inc. All rights reserved.
1
// Fig. 18.9: Stack.h
2
3
4
// Template Stack class definition derived from class List.
#ifndef STACK_H
#define STACK_H
Outline
#include "List.h" // List class definition
Stack.h
42
5
6
7
8
Erzeugung eines Stack Klassentemplate
(1 von 2)durch
private Vererbung vom List Klassentemplate
template< typename STACKTYPE >
9 class Stack : private List< STACKTYPE >
10 {
11 public:
12
// push calls the List function insertAtFront
13
void push( const STACKTYPE &data )
14
15
{
16
17
} // end function push
18
// pop calls the List function removeFromFront
19
bool pop( STACKTYPE &data )
20
{
21
insertAtFront( data );
Realisierung von push und pop über die
Basisklassenfunktionen insertAtFront
bzw. removeFromFront
return removeFromFront( data );
22
23
} // end function pop
24
// toString and isEmpty are the same as in List
25
// keyword 'using' makes them public
26
27
using List< STACKTYPE >::toString;
using List< STACKTYPE >::isEmpty;
28 }; // end class Stack
29
30 #endif
Im Fall von toString und isEmpty werden die
Basisklassenfunktionen direkt verwendet und
durch using in die öffentliche Schnittstelle der
abgeleiteten Klasse übernommen.
 2006 Pearson Education,
Inc. All rights reserved.
1
2
3
4
// Fig. 18.10: fig18_10.cpp
// Template Stack class test program.
5
6
using namespace std;
7
8
#include "Stack.h" // Stack class definition
Outline
#include <iostream>
11
12
Stack< int > intStack; // create Stack of ints
13
14
15
16
cout << "processing an integer Stack" << endl;
// push integers onto intStack
for( int i = 0; i < 3; ++i ) {
17
18
19
intStack.push( i );
cout << intStack.toString();
} // end for
20
21
int popInteger; // store int popped from stack
22
23
// pop integers from intStack
24
25
while( !intStack.isEmpty() ) {
intStack.pop( popInteger );
28
fig18_10.cpp
(1 von 3)
9 int main()
10 {
26
27
43
Ablegen der ganzen Zahlen von 0 bis 2 auf intStack
Entfernen der ganzen Zahlen von 0 bis 2 von intStack
cout << popInteger << " popped from stack" << endl;
cout << intStack.toString();
} // end while
 2006 Pearson Education,
Inc. All rights reserved.
29
30
31
Stack< double > doubleStack; // create Stack of doubles
double value = 1.1;
Outline
44
32
33
34
cout << "processing a double Stack" << endl;
35
// push floating-point values onto doubleStack
36
37
for( int j = 0; j < 3; ++j ) {
doubleStack.push( value );
38
39
40
fig18_10.cpp
(2 von 3)
Ablegen der Werte 1.1, 2.2, 3.3 auf doubleStack
cout << doubleStack.toString();
value += 1.1;
} // end for
41
42
43
44
double popDouble; // store double popped from stack
45
while( !doubleStack.isEmpty() ) {
// pop floating-point values from doubleStack
Entfernen der Werte 3.3, 2.2 und 1.1 von doubleStack
46
47
doubleStack.pop( popDouble );
cout << popDouble << " popped from stack" << endl;
48
cout << doubleStack.toString();
49
} // end while
50 } // end main
 2006 Pearson Education,
Inc. All rights reserved.
processing an integer Stack
The list is: 0
Outline
45
The list is: 1 0
The list is: 2 1 0
2 popped from stack
The list is: 1 0
fig18_10.cpp
1 popped from stack
The list is: 0
(3 von 3)
0 popped from stack
The list is empty
processing a double Stack
The list is: 1.1
The list is: 2.2 1.1
The list is: 3.3 2.2 1.1
3.3 popped from stack
The list is: 2.2 1.1
2.2 popped from stack
The list is: 1.1
1.1 popped from stack
The list is empty
All nodes destroyed
All nodes destroyed
 2006 Pearson Education,
Inc. All rights reserved.
1
// Fig. 18.11: Stackcomposition.h
2
3
// Template Stack class definition with composed List object.
#ifndef STACKCOMPOSITION_H
4
5
#define STACKCOMPOSITION_H
#include <string>
6
#include "List.h" // List class definition
7
8
template< typename STACKTYPE >
9
class Stack
10 {
Outline
46
Stack
composition.h
(1 von 2)
11 public:
12
// no programmer-defined constructor;
13
// List default constructor does initialization of stackList data element
14
15
// push calls stackList object's insertAtFront member function
16
void push( const STACKTYPE &data )
17
{
18
19
stackList.insertAtFront( data );
} // end function push
20
21
// pop calls stackList object's removeFromFront member function
22
bool pop( STACKTYPE &data )
23
{
24
25
return stackList.removeFromFront( data );
} // end function pop
 2006 Pearson Education,
Inc. All rights reserved.
26
27
28
// isEmpty calls stackList object's isEmpty member function
bool isEmpty() const
29
30
{
31
} // end function isEmpty
32
33
// toString calls stackList object's toString member function
34
35
std::string toString() const
{
36
37
return stackList.toString();
} // end function toString
Outline
47
return stackList.isEmpty();
Stack
composition.h
(2 von 2)
38 private:
39
List< STACKTYPE > stackList; // composed List object
40 }; // end class Stack
41
42 #endif
Diese Implementierung des Stack Klassentemplate enthält
das List< STACKTYPE > Objekt stackList
 2006 Pearson Education,
Inc. All rights reserved.
48
18.6 Warteschlangen
• Warteschlange (Queue)
– Der erste Wert in der Schlange kommt als erster dran,
weitere Werte folgen in einer Reihe.
• Knoten werden nur vom Kopf (Head) entfernt und nur am
Schwanz (Tail) hinzugefügt.
• Auch als FIFO (first-in, first-out) Datenstruktur bezeichnet
– Einfügen: enqueue (‘enter the queue’)
– Entfernen: dequeue (‘delete from queue’)
– Anwendungen
• Warteschlangen für
– Prozessornutzung
– Druckaufträge
– Pakete in einem Router
– Anfragen an ein Dateisystem
 2006 Pearson Education, Inc. All rights reserved.
1
2
3
// Fig. 18.12: Queue.h
// Template Queue class definition derived from class List.
#ifndef QUEUE_H
4
#define QUEUE_H
5
6
#include "List.h" // List class definition
7
8
9
template< typename QUEUETYPE >
class Queue : private List< QUEUETYPE >
Outline
49
Queue.h
Erzeugung eines Queue Klassentemplate durch
(1 Klassentemplate
von 2)
private Vererbung vom List
10 {
11 public:
12
// enqueue calls List member function insertAtBack
13
void enqueue( const QUEUETYPE &data )
14
15
{
16
} // end function enqueue
17
18
// dequeue calls List member function removeFromFront
19
bool dequeue( QUEUETYPE &data )
20
21
{
22
} // end function dequeue
23
24
// toString and isEmpty are the same as in List
25
// keyword 'using' makes them public
26
27
using List< QUEUETYPE >::toString;
using List< QUEUETYPE >::isEmpty;
insertAtBack( data );
Realisierung von enqueue und
dequeue über die Basisklassenfunktionen insertAtBack
bzw. removeFromFront
return removeFromFront( data );
28 }; // end class Queue
29
30 #endif
Im Fall von toString und isEmpty werden die
Basisklassenfunktionen direkt verwendet und
durch using in die öffentliche Schnittstelle der
abgeleiteten Klasse übernommen.
 2006 Pearson Education,
Inc. All rights reserved.
1
// Fig. 18.13: fig18_13.cpp
2
3
4
// Template Queue class test program.
5
6
using namespace std;
7
#include "Queue.h" // Queue class definition
8
9
int main()
Outline
50
#include <iostream>
10 {
11
fig18_13.cpp
(1 von 3)
Queue< int > intQueue; // create Queue of integers
12
13
14
15
16
17
cout << "processing an integer Queue" << endl;
// enqueue integers onto intQueue
for( int i = 0; i < 3; ++i ) {
Einfügen der ganzen Zahlen von 0 bis 2 in intQueue
intQueue.enqueue( i );
18
19
cout << intQueue.toString();
} // end for
20
21
int dequeueInteger; // store dequeued integer
22
23
24
25
26
27
28
// dequeue integers from intQueue
while( !intQueue.isEmpty() ) {
Entfernen der ganzen Zahlen von 0 bis 2 aus intQueue
intQueue.dequeue( dequeueInteger );
cout << dequeueInteger << " dequeued" << endl;
cout << intQueue.toString();
} // end while
 2006 Pearson Education,
Inc. All rights reserved.
29
30
31
Queue< double > doubleQueue; // create Queue of doubles
double value = 1.1;
Outline
51
32
33
34
cout << "processing a double Queue" << endl;
35
// enqueue floating-point values onto doubleQueue
36
37
for( int j = 0; j < 3; ++j ) {
doubleQueue.enqueue( value );
38
39
40
fig18_13.cpp
(2 von 3)
Einfügen der Werte 1.1, 2.2 und 3.3 in doubleQueue
cout << doubleQueue.toString();
value += 1.1;
} // end for
41
42
43
44
double dequeueDouble; // store dequeued double
45
while( !doubleQueue.isEmpty() ) {
// dequeue floating-point values from doubleQueue
Entfernen der Werte 1.1, 2.2 und 3.3 aus doubleQueue
46
46
doubleQueue.dequeue( dequeueDouble );
cout << dequeueDouble << " dequeued" << endl;
48
cout << doubleQueue.toString();
49
} // end while
50 } // end main
 2006 Pearson Education,
Inc. All rights reserved.
processing an integer Queue
The list is: 0
Outline
52
The list is: 0 1
The list is: 0 1 2
0 dequeued
The list is: 1 2
fig18_13.cpp
(3 von 3)
1 dequeued
The list is: 2
2 dequeued
The list is empty
processing a double Queue
The list is: 1.1
The list is: 1.1 2.2
The list is: 1.1 2.2 3.3
1.1 dequeued
The list is: 2.2 3.3
2.2 dequeued
The list is: 3.3
3.3 dequeued
The list is empty
All nodes destroyed
All nodes destroyed
 2006 Pearson Education,
Inc. All rights reserved.
53
18.7 Bäume
• Baum (Tree)
– Nichtlineare, zweidimensionale Datenstruktur
– Knoten von Bäumen enthalten zwei oder mehrere Links
• Knoten von Binärbäumen enthalten genau zwei Links
 2006 Pearson Education, Inc. All rights reserved.
54
18.7 Bäume
• Baum
– Terminologie
• Wurzelknoten
– Erster Knoten in einem Baum
• Kindknoten
– Mit einem übergeordneten Knoten (seinem
Elternknoten) verlinkter Knoten
– In einem Binärbaum gibt es einen rechten und einen
linken Kindknoten
• Teilbaum
– Baum, der dadurch definiert wird, dass ein Kindknoten
als Wurzel seines eigenen Baums genommen wird
• Blattknoten
– Knoten ohne Kindknoten
 2006 Pearson Education, Inc. All rights reserved.
55
Fig. 18.14 | Graphische Darstellung eines Binärbaums.
 2006 Pearson Education, Inc. All rights reserved.
56
18.7 Bäume
• Binärer Suchbaum
– Die Werte in jedem linken Teilbaum sind kleiner als der
Wert seines Elternknoten.
– Die Werte in jedem rechten Teilbaum sind größer als der
Wert seines Elternknoten.
– Kann auf sechs Arten rekursiv durchlaufen werden, davon
sind die drei wichtigsten:
• Inorder
– Linker Teilbaum, aktueller Knoten, rechter Teilbaum
• Preorder
– Aktueller Knoten, linker Teilbaum, rechter Teilbaum
• Postorder
– Linker Teilbaum, rechter Teilbaum, aktueller Knoten
 2006 Pearson Education, Inc. All rights reserved.
57
Fig. 18.15 | Ein binärer Suchbaum.
 2006 Pearson Education, Inc. All rights reserved.
1
2
3
// Fig. 18.16: Treenode.h
// Template TreeNode class definition.
#ifndef TREENODE_H
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define TREENODE_H
// forward declaration of class Tree
template< typename NODETYPE > class Tree;
Outline
58
Treenode.h
(1 von 1)
// TreeNode class-template definition
template< typename NODETYPE >
class TreeNode
Tree< NODETYPE > wird als friend von
{
TreeNode< NODETYPE > deklariert
friend class Tree< NODETYPE >;
public:
// constructor
TreeNode( const NODETYPE &d )
: leftPtr( nullptr ), // pointer to left subtree
Dieser Knoten wird als Blattknoten
data( d ), // tree node data
mit data-Wert d initialisiert
rightPtr( nullptr ) // pointer to right substree
{ }
// return copy of node's data
NODETYPE getData() const { return data; }
private:
TreeNode * leftPtr; // pointer to left subtree
NODETYPE data;
26
TreeNode * rightPtr; // pointer to right subtree
27 }; // end class TreeNode
Die Zeiger leftPtr und rightPtr zeigen auf
28
29 #endif
den linken bzw. rechten Teilbaum des Knotens
 2006 Pearson Education,
Inc. All rights reserved.
1
2
3
4
// Fig. 18.17: Tree.h
// Template Tree class definition.
#ifndef TREE_H
#define TREE_H
Outline
5
6
7
#include <iostream>
#include <iomanip>
Tree.h
8
9
10
11
#include
#include
#include
#include
(1 von 10)
<sstream>
<string>
<new>
"Treenode.h"
59
12
13 // Tree class-template definition
14 template< typename NODETYPE > class Tree
15 {
16 public:
17
Tree(); // constructor
18
~Tree(); // destructor
19
20
21
22
Tree( const Tree& ) = delete; // no copies of Tree-objects allowed
const Tree& operator=( const Tree& ) = delete; // no assignment allowed
void insertNode( const NODETYPE & );
std::string preOrderTraversal() const;
23
24
25
std::string inOrderTraversal() const;
std::string postOrderTraversal() const;
TreeNode< NODETYPE > * binaryTreeSearch( const NODETYPE & ) const;
26
std::string toString() const;
27
void deleteNode( const NODETYPE & );
28 private:
29
TreeNode< NODETYPE > * rootPtr;
 2006 Pearson Education,
Inc. All rights reserved.
30
31
32
// utility functions
void insertNodeHelper( TreeNode< NODETYPE > *&, const NODETYPE & );
33
34
35
void preOrderHelper( TreeNode< NODETYPE > *, std::stringstream & ) const;
void inOrderHelper( TreeNode< NODETYPE > *, std::stringstream & ) const;
void postOrderHelper( TreeNode< NODETYPE > *, std::stringstream & ) const;
36
37
38
TreeNode< NODETYPE > * binarySearchHelper( TreeNode< NODETYPE > *,
const NODETYPE & ) const;
void toStringHelper( TreeNode< NODETYPE >*, int, std::stringstream& ) const;
39
40
41
bool deleteNodeHelper( TreeNode< NODETYPE > *&, const NODETYPE & );
void replaceNodeHelper( TreeNode< NODETYPE > *&, TreeNode< NODETYPE > *& );
void destructorHelper( TreeNode< NODETYPE > *&);
Outline
60
Tree.h
(2 von 10)
42 }; // end class Tree
43
44 // constructor
45 template< typename NODETYPE >
46 Tree< NODETYPE >::Tree()
47 {
48
rootPtr = nullptr; // indicate tree is initially empty
49 } // end Tree constructor
50
51 // destructor
52 template< typename NODETYPE >
53 Tree< NODETYPE >::~Tree()
54 {
55
std::cerr << "Destroying nodes ...\n";
56
destructorHelper( rootPtr );
57
std::cerr << "All nodes destroyed\n\n";
58 } // end Tree destructor
59
 2006 Pearson Education,
Inc. All rights reserved.
60 // insert node in Tree
Outline
61 template< typename NODETYPE >
62 void Tree< NODETYPE >::insertNode( const NODETYPE & value )
61
63 {
64
insertNodeHelper( rootPtr, value );
65 } // end function insertNode
Tree.h
66
67 // utility function called by insertNode; receives a reference to a
68 // pointer so that the function can modify the pointer arguments's value
69 template< typename NODETYPE >
ptr ist eine Referenz für einen
Zeiger auf einen TreeNode
70 void Tree< NODETYPE >::insertNodeHelper(
71
(3 von 10)
TreeNode< NODETYPE > *& ptr, const NODETYPE & value )
72 {
73
// subtree is empty; create new TreeNode containing value
74
if( ptr == nullptr ) {
75
ptr = new TreeNode< NODETYPE >( value );
76
} // end if
77
else { // subtree is not empty
78
// data to insert is less than data in current node
79
if( value < ptr->data ) {
80
Ein neuer TreeNode wird erzeugt,
initialisiert und dem Originalzeiger in
der aufrufenden Funktion zugewiesen
insertNodeHelper( ptr->leftPtr, value );
81
} // end if
82
else {
Rekursiver Aufruf von
insertNodeHelper
83
// data to insert is greater than data in current node
84
if( ptr->data < value )
85
86
87
88
89
insertNodeHelper( ptr->rightPtr, value );
else // duplicate data value ignored
std::cerr << value << " dup" << endl;
} // end else
} // end else
90 } // end function insertNodeHelper
91
Falls der neu einzusetzende Wert identisch
mit dem Wert im Elternknoten ist, wird
der Wert nicht eingesetzt
 2006 Pearson Education,
Inc. All rights reserved.
92
93
94
95
96
97
// begin preorder traversal of Tree
template< typename NODETYPE >
std::string Tree< NODETYPE >::preOrderTraversal() const
{
std::stringstream outStream;
98
preOrderHelper( rootPtr, outStream );
99
return outStream.str();
100 } // end function preOrderTraversal
101
102 // utility function to perform preorder traversal of Tree
Outline
62
Tree.h
(4 von 10)
103template< typename NODETYPE >
104 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > * ptr,
105
std::stringstream & outStream ) const
106 {
107
if( ptr != nullptr ) {
108
outStream << ptr->data << ' '; // process node
109
preOrderHelper( ptr->leftPtr, outStream ); // traverse left subtree
110
preOrderHelper( ptr->rightPtr, outStream ); // traverse right subtree
111
} // end if
112 } // end function preOrderHelper
Schreibt die Knoten in einer Reihenfolge,
die beim Einlesen mit insertNode
wieder genau den gleichen Baum ergibt
 2006 Pearson Education,
Inc. All rights reserved.
113
Outline
114 // begin inorder traversal of Tree
115 template< typename NODETYPE >
63
116 std::string Tree< NODETYPE >::inOrderTraversal() const
117 {
Tree.h
118
std::stringstream outStream;
119
inOrderHelper( rootPtr, outStream );
120
return outStream.str();
(5 von 10)
121 } // end function inOrderTraversal
122
123 // utility function to perform inorder traversal of Tree
124 template< typename NODETYPE >
125 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > * ptr,
126
std::stringstream & outStream ) const
127 {
128
if( ptr != nullptr ) {
129
inOrderHelper( ptr->leftPtr, outStream
130
outStream << ptr->data << ' '; // process node
131
inOrderHelper( ptr->rightPtr, outStream
132
); // traverse left subtree
); // traverse right subtree
} // end if
133} // end function inOrderHelper
Durchläuft den Baum in
sortierter Reihenfolge
 2006 Pearson Education,
Inc. All rights reserved.
134
Outline
135// begin postorder traversal of Tree
136 template< typename NODETYPE >
64
137std::string Tree< NODETYPE >::postOrderTraversal() const
138{
Tree.h
139
std::stringstream outStream;
140
postOrderHelper( rootPtr, outStream );
141
return outStream.str();
(6 von 10)
142 } // end function postOrderTraversal
143
144 // utility function to perform postorder traversal of Tree
145 template< typename NODETYPE >
146 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > * ptr,
147
std::stringstream & outStream ) const
148 {
149
if( ptr != nullptr ) {
150
postOrderHelper( ptr->leftPtr, outStream
151
postOrderHelper( ptr->rightPtr, outStream
152
outStream << ptr->data << ' '; // process node
153
); // traverse left subtree
); // traverse right subtree
} // end if
154 } // end function postOrderHelper
Besucht alle Knoten des Baumes ‘von
außen her’, d.h. die Blätter zuerst
 2006 Pearson Education,
Inc. All rights reserved.
155 // begin binary search
Outline
156 template< typename NODETYPE >
157 TreeNode< NODETYPE > * Tree< NODETYPE >::binaryTreeSearch
158
159 {
160
65
( const NODETYPE & val ) const
return binarySearchHelper( rootPtr, val );
Tree.h
161 } // end function binaryTreeSearch
162
(7 von 10)
163 // do a binary search on the Tree; NODETYPE::operator< required
164 template< typename NODETYPE >
165 TreeNode< NODETYPE > * Tree< NODETYPE >::binarySearchHelper
166
( TreeNode< NODETYPE > * ptr, const NODETYPE & value ) const
167 {
168
// if value is not found
169
if( ptr == nullptr )
170
171
172
ptr enthält den Zeiger auf
den aktuellen TreeNode
return nullptr;
if( value < ptr->getData() ) { // search value less than current data
return binarySearchHelper( ptr->leftPtr, value );
Rekursiver Aufruf von
binarySearchHelper
173
} // end if
174
else if( ptr->getData() < value ) { // value greater than current data
175
return binarySearchHelper( ptr->rightPtr, value );
176
} // end else if
177
else { // match
178
179
return ptr;
} // end else
Der Zeiger auf den TreeNode, der den
gesuchten Wert enthält, wird zurückgegeben
180 } // end function binarySearchHelper
181
 2006 Pearson Education,
Inc. All rights reserved.
186 // return the tree as a string
Outline
187 template< typename NODETYPE >
188 std::string Tree< NODETYPE >::toString() const
189 {
190
std::stringstream outStream;
191
toStringHelper( rootPtr, 2, outStream );
192
return outStream.str();
193 } // end function toString
Tree.h
194
195 // utility function to return the tree as a string
196 template< typename NODETYPE >
197 void Tree< NODETYPE >::toStringHelper( TreeNode< NODETYPE > * ptr,
198
int totalSpaces, std::stringstream & outStream ) const
199{
Leerzeichen
200
if( ptr != nullptr ) {
201
toStringHelper( ptr->rightPtr, totalSpaces + 5, outStream);
202
outStream << setw( totalSpaces ) << ptr->data << '\n';
203
toStringHelper( ptr->leftPtr, totalSpaces + 5, outStream);
204
} // end if
205 } // end function outputTreeHelper
206
207 // delete node in tree
66
(8 von 10)
für die Formatierung
der Ausgabe
208 template< typename NODETYPE >
209 void Tree< NODETYPE >::deleteNode( const NODETYPE & value )
210 {
211
std::cerr << "deletNode called for: " << value;
212
if( deleteNodeHelper( rootPtr, value ) )
213
std::cerr << " <- node deleted! " << endl;
214
else
215
std::cerr << " <- node not found! " << endl;
216 } // end function binarySearchHelper
217
 2006 Pearson Education,
Inc. All rights reserved.
67
18.7 Bäume
• Löschen einzelner Elemente
– Drei Varianten sind möglich
1.
Zu löschendes Element ist ein Blatt:
Direktes Entfernen ist möglich.
2.
Zu löschendes Element hat genau einen Nachfolger:
Zu löschendes Element wird durch den Nachfolger ersetzt.
3.
Zu löschendes Element hat zwei Nachfolger:
Der Wert im zu löschenden Element wird durch den
kleinsten Wert im rechten Teilbaum ersetzt. Danach wird
das Element mit dem kleinsten Wert im rechten Teilbaum
ausgehängt (d.h. durch seinen rechten Nachfolger ersetzt)
und gelöscht.
 2006 Pearson Education, Inc. All rights reserved.
218 // utility function called by deleteNode; receives a reference to a
219 // pointer so that the function can modify the pointer arguments's value
220 template< typename NODETYPE >
Outline
68
221 bool Tree< NODETYPE >::deleteNodeHelper(
222
TreeNode< NODETYPE > *& ptr, const NODETYPE & value )
223 {
224
TreeNode< NODETYPE > * tempPtr;
225
if( ptr == nullptr ) // data not found in tree; no deletion
226
227
return false;
else
228
229
230
231
232
ptr ist eine Referenz
Tree.h für einen
Zeiger auf einen TreeNode
possible
(9 von 10)
// data to delete is less than data in current node; move to left child:
if( value < ptr->data )
return deleteNodeHelper( ptr->leftPtr, value );
Rekursiver Aufruf von
deleteNodeHelper
else
// data to delete greater than data in current node; move to right child:
233
234
if( ptr->data < value )
return deleteNodeHelper( ptr->rightPtr, value );
235
236
else {
tempPtr = ptr; // node to be deleted
237
// one (or zero) left child: child node takes place of deleted node
238
239
if( tempPtr->rightPtr == nullptr )
ptr = tempPtr->leftPtr;
240
241
else
// one right child: child node takes place of deleted node
242
if( tempPtr->leftPtr == nullptr )
243
244
ptr = tempPtr->rightPtr;
else // two children: replace value to be deleted
245
246
replaceNodeHelper( tempPtr, tempPtr->rightPtr );
delete tempPtr;
247
return true;
248
}
249 } // end function deleteNodeHelper
Hilfsfunktion zum Austauschen
der Werte zweier Knoten 2006 Pearson Education,
Inc. All rights reserved.
250
251 // utility function called by deleteNodeHelper to replace value
252 // to be deleted with smallest value in right subtree
Outline
69
253template< typename NODETYPE >
254 void Tree< NODETYPE >::replaceNodeHelper(
255
256{
257
TreeNode< NODETYPE > *& tempPtr, TreeNode< NODETYPE > *& right )
if( right->leftPtr != nullptr )
258
259
260
261
// look for smallest value in right subtree
replaceNodeHelper( tempPtr, right->leftPtr );
Tree.h
(10 von 10)
else {
// replace value to be deleted with smallest value in right subtree
262
tempPtr->data = right->data;
263
264
tempPtr = right; // now this node has to be deleted
right = right->rightPtr; // unlink the node that will be deleted
265
}
266 } // end function replaceNodeHelper
267
268 // utility function called by destructor for deletion of subtrees
269 // using postorder traversal
270 template< typename NODETYPE >
271void Tree< NODETYPE >::destructorHelper( TreeNode< NODETYPE > *& ptr )
272 {
273
if( ptr != nullptr ) {
274
destructorHelper( ptr->leftPtr ); // delete left subtree
275
276
destructorHelper( ptr->rightPtr ); // delete right subtree
std::cerr << ptr->getData() << ' ';
277
278
delete ptr; // delete root
ptr = nullptr; // empty tree: rootPtr == nullptr
279
}
280 } // end function destructorHelper
281 #endif
 2006 Pearson Education,
Inc. All rights reserved.
1
// Fig. 18.20: fig18_20.cpp
2
// Tree class test program.
3
#include <iostream>
4
#include <fstream>
5
#include <string>
6
#include <array>
7
using namespace std;
Outline
fig18_20.cpp
8
9
70
(1 von 5)
#include "Tree.h" // Tree class definition
10 #include "Employee.h" // Employee class as defined in Kapitel 11 (fig11_05)
11
12 int main()
13 {
Baum intTree vom Typ
Tree< int > instanzieren
14
Tree< int > intTree; // create Tree of int values
15
array< int, 15 > intValues =
16
{ 50, 25, 75, 12, 33, 67, 88, 10, 13, 35, 85, 68, 90, 52, 30 };
17
18
// insert 15 integers to intTree
19
for( int i = 0; i < 15; ++i ) {
20
21
int–Werte in den Binärbaum einsetzen
intTree.insertNode( intValues[ i ] );
} // end for
22
23
cout << "intTree: Preorder traversal\n";
24
cout << intTree.preOrderTraversal();
25
cout << "\nintTree: Inorder traversal\n";
26
cout << intTree.inOrderTraversal();
27
cout << "\nintTree: Postorder traversal\n";
28
cout << intTree.postOrderTraversal();
intTree durchlaufen
29
 2006 Pearson Education,
Inc. All rights reserved.
30
Tree< Employee > employeeTree; // create Tree of Employees
31
string lastName, firstName;
Outline
32
33
ifstream in( "data.txt", ios::in );
34
if( !in ) {
Baum employeeTree vom Typ
Tree< Employee > instanzieren
35
cerr << "File could not be opened." << endl;
36
exit( 1 );
37
fig18_20.cpp
} // end if
(2 von 5)
38
39
40
while( in >> lastName >> firstName )
employeeTree.insertNode( Employee( firstName, lastName ) );
41
42
cout << "\n\nemployeeTree: Inorder traversal\n ";
43
cout << employeeTree.inOrderTraversal();
44
Employee–Werte in den Binärbaum einsetzen
employeeTree durchlaufen
45
// search a value in intTree
46
int intValue;
47
cout << "\nEnter int value to search for: ";
48
cin >> intValue ;
49
// create a pointer with the value entered by the user
50
TreeNode< int > * ptr = intTree.binaryTreeSearch( intValue );
51
if( ptr != nullptr ) // a value is found
52
53
54
71
cout << ptr->getData() << " was found\n";
else // value not found
cout << "Element was not found\n";
55
 2006 Pearson Education,
Inc. All rights reserved.
56
// delete a value in intTree
57
cout << "\nEnter int value to delete: ";
58
cin >> intValue ;
59
// delete node with the value entered by the user
60
intTree.deleteNode( intValue );
61
cout << "\nintTree : Inorder traversal\n";
62
cout << intTree.inOrderTraversal();
63
cout << endl;
64
cout << "\nThe tree is:\n";
65
cout << intTree.toString();
66
cout << endl << endl;
Outline
72
fig18_20.cpp
(3 von 5)
67 } // end main
intTree:
50 25 12
intTree:
10 12 13
intTree:
10 13 12
Preorder traversal
10 13 33 30 35 75 67 52 68 88 85 90
Inorder traversal
25 30 33 35 50 52 67 68 75 85 88 90
Postorder traversal
30 35 33 25 52 68 67 85 90 88 75 50
employeeTree: Inorder traversal
Austen, Kate
Burke, Juliet
Carlyle, Boone
Dawson, Michael
Faraday, Daniel
Ford, James
Hume, Desmond
Jarrah, Sayid
Kwon, Jin-Soo
Kwon, Sun-Hwa
Linus, Benjamin
Littleton, Claire
Lloyd, Walter
Locke, Jonathan
 2006 Pearson Education,
Inc. All rights reserved.
Pace, Charlie
Reyes, Hugo
Rousseau, Danielle
Rutherford, Shannon
Shephard, Christian
Shephard, Jack
Straume, Miles
Widmore, Charles
Widmore, Penelope
Enter int value to search for: 2
Element was not found
Outline
73
fig18_20.cpp
(4 von 5)
Enter int value to delete: 2
deleteNode called for: 2 <- node not found!
intTree: Inorder traversal
10 12 13 25 30 33 35 50 52 67 68 75 85 88 90
The tree is:
90
88
85
75
68
67
52
50
35
33
30
25
13
12
10
 2006 Pearson Education,
Inc. All rights reserved.
Enter int value to search for: 67
67 was found
Enter int value to delete: 67
deleteNode called for: 67 <- node deleted!
Outline
Alternative für Suchen und Entfernen eines
Elementes aus dem intTree
intTree: Inorder traversal
10 12 13 25 30 33 35 50 52 68 75 85 88 90
fig18_20.cpp
The tree is:
(5 von 5)
90
74
88
85
75
68
52
50
35
33
30
25
13
12
10
 2006 Pearson Education,
Inc. All rights reserved.
75
18.7 Bäume
• Anwendungen von binären Suchbäumen
– Entfernen von Duplikaten
• Duplikat folgt beim Einsetzen dem gleichen Pfad wie das Original
• Duplikate können beim Vergleich mit dem Original verworfen
werden (oder z.B. gezählt werden: s. Praktikum 4).
– Suchen (in einem ‘ausgeglichenen’ binären Suchbaum)
• Hat Laufzeit O(log n)
– Jeder Vergleich eines Knotens mit dem Suchschlüssel
eliminiert die Hälfte der Knoten.
– Es sind maximal log2 n Vergleiche erforderlich.
– Sortieren (‘binary tree sort’)
• Das Inorder-Durchlaufen eines binären Suchbaums sorgt für eine
Verarbeitung der Werte in ansteigender Ordnung.
 2006 Pearson Education, Inc. All rights reserved.
Herunterladen