2006 pearson education, inc. all rights reserved. 1 21 data structures
Post on 21-Dec-2015
214 views
TRANSCRIPT
2
2006 Pearson Education, Inc. All rights reserved.
21.2 Self-Referential Classes
• Self-referential class– Contains a pointer member that points to an object of the
same class type
– Example• Class Node{ … Node *nextPtr;};
– Pointer data member nextPtr is a link
• Can tie a Node to another Node
4
2006 Pearson Education, Inc. All rights reserved.
21.3 Dynamic Memory Allocation and Data Structures
• Dynamic memory allocation– Enables a program to obtain more memory at execution
time• That memory can be released when it is no longer needed
– Limited by amount of physical or virtual memory• Memory must be shared among many programs
Common Programming Error 21.1
Not setting the link in the last node of a linked data structure to null (0) is a (possibly fatal) logic error.
6
Lets look at lists:
Using Arraysfixed sizeMust shift to add something to the front or delete the first element (or anywhere in the middle)
Easy to add at the endUsing Vectors
Not fixed sizeStill have to shift to add something
8
complexity
To add an element to a list of size n: O(n)
To delete an element to a list of size n: O(n)
Shifting is an expensive operation since it involves a copy. Not practical for large lists!
Can we do something else?
9
2006 Pearson Education, Inc. All rights reserved.
21.4 Linked Lists
• Linked list– Linear collection of self-referential class objects
• Called nodes
• Connected by pointer links
– Accessed via a pointer to the first node• Subsequent nodes are accessed via previous node’s link
– By convention, link in last node is set to null pointer 0
– Additional nodes are dynamically allocated as necessary
10
2006 Pearson Education, Inc. All rights reserved.
21.4 Linked Lists (Cont.)
• Linked list (Cont.)– Advantages over arrays
• Linked lists are dynamic
– Length can increase or decrease as necessary
• Efficient insertion of new elements into a sorted list
– Existing list elements do not need to be moved
Performance Tip 21.1
An array can be declared to contain more elements than the number of items expected, but this can waste memory. Linked lists can provide better memory utilization in these situations. Linked lists allow the program to adapt at runtime. Note that class template vector (introduced in Section 7.11) implements a dynamically resizable array-based data structure.
Performance Tip 21.2
Insertion and deletion in a sorted array can be time consuming—all the elements following the inserted or deleted element must be shifted appropriately. A linked list allows efficient insertion operations anywhere in the list.
Performance Tip 21.3
The elements of an array are stored contiguously in memory. This allows immediate access to any array element, because the address of any element can be calculated directly based on its position relative to the beginning of the array. Linked lists do not afford such immediate “direct access” to their elements. So accessing individual elements in a linked list can be considerably more expensive than accessing individual elements in an array. The selection of a data structure is typically based on the performance of specific operations used by a program and the order in which the data items are maintained in the data structure. For example, it is typically more efficient to insert an item in a sorted linked list than a sorted array.
Performance Tip 21.4
Using dynamic memory allocation (instead of fixed-size arrays) for data structures that grow and shrink at execution time can save memory. Keep in mind, however, that pointers occupy space and that dynamic memory allocation incurs the overhead of function calls.
alice barney batman robin superman
1st element 2nd element 3rd element 4th element 5th element
To add an element named “powerranger”
alice barney batman robin superman
powerranger
A graphical representation of a linked list
HeadOfList
19
int main()
{
ListNode n1(5);
ListNode n2(4);
n1.nextPtr = &n2;
n2.nextPtr = new ListNode (7);
ListNode *pp;
pp= &n1;
for(int I = 0; i<2; i++) {
pp=pp->nextPtr;
cout <<pp->getData() <<endl;
}
class ListNode {public: ListNode( const int & ); // constructor int getData() const; // return data in
node// everything is public for this example int data; // data ListNode *nextPtr; // next node in list}; // end class ListNode
ListNode::ListNode( const int &info ) : data( info ), nextPtr( 0 ) { // empty body } // end ListNode
constructor
int ListNode::getData() const { return data; } // end function getData
20
int main(){ListNode *p1,* p2*,p3;p1= new ListNode (7);P1->nextPtr=new ListNode(5);P3 = new ListNode(6);P3->nextPtr=p1;ListNode *pp=p3;for(int I = 0; i<2; i++) {cout <<pp->getData() <<endl; pp=pp->nextPtr;;}
21
Int data
ListNode *nextPtr
Holds an address of a ListNode
int main()
{
ListNode n1(5);
ListNode n2(4);
n1.nextPtr = &n2;
n2.nextPtr = new ListNode (7);
ListNode *pp;
pp= &n1;
for(int I = 0; i<2; i++) {
pp=pp->nextPtr;
cout <<pp->getData() <<endl;
}
22
Have a class
That includes the listnode class and that has all the functions of a list:
insertAtFront
insertAtBack
removeFromFront
RemoveFromBack
Etc….
23
Problem: Listnode has everything public
Let the new class LIST be a friend of listnode and make listnode private.
24
class List; class ListNode { friend class List; // make List a friendpublic: ListNode( const int & ); // constructor int getData() const; // return data in nodeprivate: int data; // data ListNode *nextPtr; // next node in list}; // end class ListNode
ListNode::ListNode( const int &info ) : data( info ), nextPtr( 0 ) { // empty body} // end ListNode constructor
int ListNode::getData() const { return data; } // end function getData
File: ListNode.h
NOTE FORWARD DECLARATION HERE SO that when the statement “friend class List” is encountered the compiler knows that the definition for class List will be coming…..
25#include <iostream>using std::cout;#include "ListnodeINT.h" // ListNode class definition
class List {public: List(); // constructor ~List(); // destructor void insertAtFront( const int & ); void insertAtBack( const int & ); bool removeFromFront( int & ); bool removeFromBack( int & ); bool isEmpty() const; void print() const;private: ListNode *firstPtr; // pointer to first node ListNode *lastPtr; // pointer to last node -- optional
// utility function to allocate new node ListNode *getNewNode( const int& );}; // end class List
28
ListNode getnewNode(const in &value)
ListNode *List::getNewNode(const int &value )
{
return new ListNode( value );
} // end function getNewNode
29
insertAtFront(const int &value)
void List::insertAtFront( const int &value ){ ListNode *newPtr = getNewNode( value ); // new
node
if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; // new list has only one
node else // List is not empty { newPtr->nextPtr = firstPtr; // point new node to
previous 1st node firstPtr = newPtr; // aim firstPtr at new node } // end else} // end function insertAtFront
30
insertAtBack
void List::insertAtBack( const int &value ){ ListNode *newPtr = getNewNode( value ); // new node
if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; // new list has only one
node else // List is not empty { lastPtr->nextPtr = newPtr; // update previous last
node lastPtr = newPtr; // new last node } // end else} // end function insertAtBack
31
bool removeFromFront(int &value)
bool List::removeFromFront( int &value ){ if ( isEmpty() ) // List is empty return false; // delete unsuccessful else { ListNode *tempPtr = firstPtr; // hold tempPtr to delete
if ( firstPtr == lastPtr ) firstPtr = lastPtr = 0; // no nodes remain after removal else firstPtr = firstPtr->nextPtr; // point to previous 2nd node
value = tempPtr->data; // return data being removed delete tempPtr; // reclaim previous front node return true; // delete successful } // end else} // end function removeFromFront
32
removeFromBackbool List::removeFromBack( int &value ){ if ( isEmpty() ) // List is empty return false; // delete unsuccessful else { ListNode *tempPtr = lastPtr; // hold tempPtr to delete
if ( firstPtr == lastPtr ) // List has one element firstPtr = lastPtr = 0; // no nodes remain after removal else { ListNode *currentPtr = firstPtr;
// locate second-to-last element while ( currentPtr->nextPtr != lastPtr ) currentPtr = currentPtr->nextPtr; // move to next node
lastPtr = currentPtr; // remove last node currentPtr->nextPtr = 0; // this is now the last node } // end else
value = tempPtr->data; // return value from old last node delete tempPtr; // reclaim former last node return true; // delete successful } // end else} // end function removeFromBack
33
void List::print() const{ if ( isEmpty() ) // List is empty { cout << "The list is empty\n\n"; return; } // end if
ListNode *currentPtr = firstPtr;
cout << "Am at print The list is: ";
while ( currentPtr != 0 ) // get element data { cout << currentPtr->data << ' '; currentPtr = currentPtr->nextPtr; } // end while
cout << "\n\n";} // end function print
35
#include “ListI.h”int main(){
List alist; bool success;alist.insertAtFront(1);alist.insertAtFront(2);alist.insertAtFront(3); //list is 3 2 1alist.insertAtBack(4); //list is now 3 2 1 4alist.print();int a[100];alist.copylisttoarray(a);for (int i= 0; i< 4; i++) cout <<a[i];
36
An example of data hiding
The list is an abstract data type --- the implementation can be hidden from its use!
37
Write a menu based main program which asks the user what they want to do with the list and then performs that action…..
38
What happens with this code?
int main(){ // test List of int values List integerList; List int2list; for (int i = 0; i < 10; i++) integerList.insertAtFront(i);
int2list = integerList;
cout << "testing original" << endl; integerList.print(); cout << "testing copy" << endl; int2list.print();
integerList.insertAtBack(11); cout << "testing original" << endl; integerList.print(); cout << "testing copy" << endl; int2list.print();}
40
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 21.3: Listnode.h
2 // Template ListNode class definition.
3 #ifndef LISTNODE_H
4 #define LISTNODE_H
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;
9
10 template< typename NODETYPE>
11 class ListNode
12 {
13 friend class List< NODETYPE >; // make List a friend
14
15 public:
16 ListNode( const NODETYPE & ); // constructor
17 NODETYPE getData() const; // return data in node
18 private:
19 NODETYPE data; // data
20 ListNode< NODETYPE > *nextPtr; // next node in list
21 }; // end class ListNode
22
23 // constructor
24 template< typename NODETYPE>
25 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
26 : data( info ), nextPtr( 0 )
27 {
28 // empty body
29 } // end ListNode constructor
Outline
Listnode.h
(1 of 2)
Member data stores a value of type parameter NODETYPE
Member nextPtr stores a pointer to the next ListNode object in the linked list
Declare class List< NODETYPE > as a friend
41
2006 Pearson Education, Inc. All rights reserved.
30
31 // return copy of data in node
32 template< typename NODETYPE >
33 NODETYPE ListNode< NODETYPE >::getData() const
34 {
35 return data;
36 } // end function getData
37
38 #endif
Outline
Listnode.h
(2 of 2)
42
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 21.4: List.h
2 // Template List class definition.
3 #ifndef LIST_H
4 #define LIST_H
5
6 #include <iostream>
7 using std::cout;
8
9 #include "listnode.h" // ListNode class definition
10
11 template< typename NODETYPE >
12 class List
13 {
14 public:
15 List(); // constructor
16 ~List(); // destructor
17 void insertAtFront( const NODETYPE & );
18 void insertAtBack( const NODETYPE & );
19 bool removeFromFront( NODETYPE & );
20 bool removeFromBack( NODETYPE & );
21 bool isEmpty() const;
22 void print() const;
23 private:
24 ListNode< NODETYPE > *firstPtr; // pointer to first node
25 ListNode< NODETYPE > *lastPtr; // pointer to last node
26
27 // utility function to allocate new node
28 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
29 }; // end class List
30
Outline
List.h
(1 of 7)
private data members firsrtPtr (a pointer to the first ListNode in a List) and lastPtr (a pointer to the last ListNode in a List)
43
2006 Pearson Education, Inc. All rights reserved.
31 // default constructor
32 template< typename NODETYPE >
33 List< NODETYPE >::List()
34 : firstPtr( 0 ), lastPtr( 0 )
35 {
36 // empty body
37 } // end List constructor
38
39 // destructor
40 template< typename NODETYPE >
41 List< NODETYPE >::~List()
42 {
43 if ( !isEmpty() ) // List is not empty
44 {
45 cout << "Destroying nodes ...\n";
46
47 ListNode< NODETYPE > *currentPtr = firstPtr;
48 ListNode< NODETYPE > *tempPtr;
49
50 while ( currentPtr != 0 ) // delete remaining nodes
51 {
52 tempPtr = currentPtr;
53 cout << tempPtr->data << '\n';
54 currentPtr = currentPtr->nextPtr;
55 delete tempPtr;
56 } // end while
57 } // end if
58
59 cout << "All nodes destroyed\n\n";
60 } // end List destructor
Outline
List.h
(2 of 7)
Initialize both pointers to 0 (null)
Ensure that all ListNode objects in a List object are destroyed when that List object is destroyed
44
2006 Pearson Education, Inc. All rights reserved.
Outline
List.h
(6 of 7)Determine whether the List is empty
Return a dynamically allocated ListNode object
46
Insert at front:
What if there are none in the list?
Make sure the first pointer is set properly.
What if there is only one?
47
Outline
List.h
(3 of 7)
Places a new node at the front of the list
Use function getNewNode to allocate a new ListNode containing value and assign it to newPtr
If the list is empty, then both firstPtr and lastPtr are set to newPtr
Thread the new node into the list so that the new node points to the old first node and firstPtr points to the new node
49
2006 Pearson Education, Inc. All rights reserved.
Outline
List.h
(3 of 7)
Use function getNewNode to allocate a new listNode containing value and assign it to newPtr
If the list is empty, then both firstPtr and lastPtr are set to newPtr
Thread the new node into the list so that the old last node points to the new node and lastPtr points to the new node
51
2006 Pearson Education, Inc. All rights reserved.
91
92 // delete node from front of list
93 template< typename NODETYPE >
94 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
95 {
96 if ( isEmpty() ) // List is empty
97 return false; // delete unsuccessful
98 else
99 {
100 ListNode< NODETYPE > *tempPtr = firstPtr; // hold tempPtr to delete
101
102 if ( firstPtr == lastPtr )
103 firstPtr = lastPtr = 0; // no nodes remain after removal
104 else
105 firstPtr = firstPtr->nextPtr; // point to previous 2nd node
106
107 value = tempPtr->data; // return data being removed
108 delete tempPtr; // reclaim previous front node
109 return true; // delete successful
110 } // end else
111 } // end function removeFromFront
112
Outline
List.h
(4 of 7)
Removes the front node of the list and copies the node value to the reference parameter
Return false if an attempt is made to remove a node from an empty list
Save a pointer to the first node, which will be removed
If the list has only one element, leave the list empty
Set firstPtr to point to the second node (the new first node)
Copy the removed node’s data to reference parameter value
delete the removed node
53
2006 Pearson Education, Inc. All rights reserved.
113 // delete node from back of list
114 template< typename NODETYPE >
115 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
116 {
117 if ( isEmpty() ) // List is empty
118 return false; // delete unsuccessful
119 else
120 {
121 ListNode< NODETYPE > *tempPtr = lastPtr; // hold tempPtr to delete
122
123 if ( firstPtr == lastPtr ) // List has one element
124 firstPtr = lastPtr = 0; // no nodes remain after removal
125 else
126 {
127 ListNode< NODETYPE > *currentPtr = firstPtr;
128
129 // locate second-to-last element
130 while ( currentPtr->nextPtr != lastPtr )
131 currentPtr = currentPtr->nextPtr; // move to next node
132
133 lastPtr = currentPtr; // remove last node
134 currentPtr->nextPtr = 0; // this is now the last node
135 } // end else
136
137 value = tempPtr->data; // return value from old last node
138 delete tempPtr; // reclaim former last node
139 return true; // delete successful
140 } // end else
Outline
List.h
(5 of 7)
Removes the back node of the list and copies the node value to the reference parameter
Return false if an attempt is made to remove a node from an empty list
Save a pointer to the last node, which will be removed
If the list has only one element, leave the list empty
Assign currentPtr the address of the first node to prepare to “walk the list”
“Walk the list” until currentPtr points to the node before the last node, which will be the new last node
Make the currentPtr node the new last node
Copy the removed node’s data to reference parameter value
delete the removed node
54
2006 Pearson Education, Inc. All rights reserved.
Outline
List.h
(6 of 7)
167
168 ListNode< NODETYPE > *currentPtr = firstPtr;
169
170 cout << "The list is: ";
171
172 while ( currentPtr != 0 ) // get element data
173 {
174 cout << currentPtr->data << ' ';
175 currentPtr = currentPtr->nextPtr;
176 } // end while
177
178 cout << "\n\n";
179 } // end function print 180 181 #endif
55
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 21.5: Fig21_05.cpp
2 // List class test program.
3 #include <iostream>
4 using std::cin;
5 using std::cout;
6 using std::endl;
7
8 #include <string>
9 using std::string;
10
11 #include "List.h" // List class definition
12
13 // function to test a List
14 template< typename T >
15 void testList( List< T > &listObject, const string &typeName )
16 {
17 cout << "Testing a List of " << typeName << " values\n";
18 instructions(); // display instructions
19
20 int choice; // store user choice
21 T value; // store input value
22
23 do // perform user-selected actions
24 {
25 cout << "? ";
26 cin >> choice;
27
Outline
Fig21_05.cpp
(1 of 6)
56
2006 Pearson Education, Inc. All rights reserved.
28 switch ( choice )
29 {
30 case 1: // insert at beginning
31 cout << "Enter " << typeName << ": ";
32 cin >> value;
33 listObject.insertAtFront( value );
34 listObject.print();
35 break;
36 case 2: // insert at end
37 cout << "Enter " << typeName << ": ";
38 cin >> value;
39 listObject.insertAtBack( value );
40 listObject.print();
41 break;
42 case 3: // remove from beginning
43 if ( listObject.removeFromFront( value ) )
44 cout << value << " removed from list\n";
45
46 listObject.print();
47 break;
48 case 4: // remove from end
49 if ( listObject.removeFromBack( value ) )
50 cout << value << " removed from list\n";
51
52 listObject.print();
53 break;
54 } // end switch
55 } while ( choice != 5 ); // end do...while
56
Outline
Fig21_05.cpp
(2 of 6)
57
2006 Pearson Education, Inc. All rights reserved.
57 cout << "End list test\n\n";
58 } // end function testList
59
60 // display program instructions to user
61 void instructions()
62 {
63 cout << "Enter one of the following:\n"
64 << " 1 to insert at beginning of list\n"
65 << " 2 to insert at end of list\n"
66 << " 3 to delete from beginning of list\n"
67 << " 4 to delete from end of list\n"
68 << " 5 to end list processing\n";
69 } // end function instructions
70
71 int main()
72 {
73 // test List of int values
74 List< int > integerList;
75 testList( integerList, "integer" );
76
77 // test List of double values
78 List< double > doubleList;
79 testList( doubleList, "double" );
80 return 0;
81 } // end main
Outline
Fig21_05.cpp
(3 of 6)
58
2006 Pearson Education, Inc. All rights reserved.
Outline
Fig21_05.cpp
(4 of 6)
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 end list processing ? 1 Enter integer: 1 The list is: 1 ? 1 Enter integer: 2 The list is: 2 1 ? 2 Enter integer: 3 The list is: 2 1 3 ? 2 Enter integer: 4 The list is: 2 1 3 4 ? 3 2 removed from list The list is: 1 3 4 (continued at top of next slide... )
59
2006 Pearson Education, Inc. All rights reserved.
Outline
Fig21_05.cpp
(5 of 6)
(...continued from bottom of previous slide) ? 3 1 removed from list The list is: 3 4 ? 4 4 removed from list The list is: 3 ? 4 3 removed from list The list is empty ? 5 End list test Testing a List of double 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 end list processing ? 1 Enter double: 1.1 The list is: 1.1 ? 1 Enter double: 2.2 The list is: 2.2 1.1 (continued at top of next slide... )
60
2006 Pearson Education, Inc. All rights reserved.
Outline
Fig21_05.cpp
(6 of 6)
(...continued from bottom of previous slide) ? 2 Enter double: 3.3 The list is: 2.2 1.1 3.3 ? 2 Enter double: 4.4 The list is: 2.2 1.1 3.3 4.4 ? 3 2.2 removed from list The list is: 1.1 3.3 4.4 ? 3 1.1 removed from list The list is: 3.3 4.4 ? 4 4.4 removed from list The list is: 3.3 ? 4 3.3 removed from list The list is empty ? 5 End list test All nodes destroyed All nodes destroyed
Error-Prevention Tip 21.1
Assign null (0) to the link member of a new node. Pointers should be initialized before they are used.
62
2006 Pearson Education, Inc. All rights reserved.
21.4 Linked Lists (Cont.)
• Linked list (Cont.)– Circular, singly linked list
• Pointer in last node points back to first node
– Doubly linked list• Each node has a link to next node and a link to previous node
• Two “start pointers”
– One to first node, one to last node
• Allows traversals both forward and backward
– Circular, doubly linked list• Forward link of last node points back to first node
• Backward link of first node points to last node