Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Linked List (II) Ying Wu Electrical Engineering & Computer Science Northwestern University EECS 230 Lectures Series.

Similar presentations


Presentation on theme: "1 Linked List (II) Ying Wu Electrical Engineering & Computer Science Northwestern University EECS 230 Lectures Series."— Presentation transcript:

1 1 Linked List (II) Ying Wu Electrical Engineering & Computer Science Northwestern University yingwu@ece.northwestern.edu EECS 230 Lectures Series

2 2 Self-Referential Classes self-referential class –class that contains a pointer to a class object of the same type –can be linked together to form useful data structures such as lists, queues, stacks and trees –terminated with a NULL pointer (0) Two self-referential class objects linked together 1015 NULL pointer (points to nothing) Data member and pointer

3 3 Node Class class Node { public: Node( const int & ); // constructor int getData() const; // return data in the node int data; // data. Actually, it can be other types or classes Node *nextPtr; // next node in the list }; // Constructor Node::Node( const int &info ) : data( info ), nextPtr( 0 ) { } // Return a copy of the data in the node Node::getData() const { return data; }

4 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 of the list –subsequent nodes are accessed via the link-pointer member –the link pointer in the last node is set to null to mark the list’s end Use a linked list instead of an array when –the number of data elements is unpredictable –the list needs to be sorted

5 5 Linked List H E L L firstPtr lasttPtr O

6 6 class List { public: List(); // constructor ~List(); // destructor voidinsertAtFront( const int & ); voidinsertAtBack( const int & ); boolremoveFromFront( int & ); boolremoveFromBack( int & ); boolisEmpty() const; voidprint() const; int Length() const; Node&Search( const int& data) const; Node&Index(const int& index); Node&operator[](const int& index); boolinsertAfter( const int& data, const int& pos); private: Node *firstPtr; // pointer to first node Node *lastPtr; // pointer to last node Node *getNewNode( const int & ); // Utility to allocate a new node };

7 7 // constructor List::List() : firstPtr( 0 ), lastPtr( 0 ) { // empty } // Is the List empty? bool List::isEmpty() const { return firstPtr == 0; }

8 8 // Return a pointer to a newly allocated node Node *List::getNewNode( const int &value ) { Node *ptr = new Node( value ); // look at this! assert( ptr != 0 ); return ptr; } // Display the contents of the List void List::print() const { if ( isEmpty() ) { cout << "The list is empty\n\n"; return; } Node *currentPtr = firstPtr; cout << "The list is: "; while ( currentPtr != 0 ) { cout data << ' '; currentPtr = currentPtr->nextPtr; // like the increment operation } cout << "\n\n"; }

9 9 void List::insertAtFront( const int & value) { Node *newPtr = getNewNode(value); if ( isEmpty() ) // List is empty: trivial case firstPtr = lastPtr = newPtr; else { // List is not empty: non-trivial case newPtr->nextPtr = firstPtr; // step 1 firstPtr = newPtr; // step 2 } void List::insertAtBack( const int& value) { Node *newPtr = getNewNode(value); if ( isEmpty() ) // List is empty: trivial case firstPtr = lastPtr = newPtr; else { // List is not empty: non-trivial case lastPtr->nextPtr = newPtr; // step 1 lastPtr = newPtr; // step 2 }

10 10 insertAtFront 5 newPtr 79 firstPtr if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; else { // List is not empty newPtr->nextPtr = firstPtr; firstPtr = newPtr; }

11 11 insertAtBack 5 newPtr 79 firstPtr lastPtr if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; else { // List is not empty lastPtr->nextPtr = newPtr; lastPtr = newPtr; }

12 12 bool List::removeFromFront( int & value) { if ( isEmpty() ) // List is empty return false; // delete unsuccessful else { Node *tempPtr = firstPtr; // step I: remember what to delete if ( firstPtr == lastPtr ) // trivial case firstPtr = lastPtr = 0; else // non-trivial case firstPtr = firstPtr->nextPtr; // step II value = tempPtr->data; // step III: retrieve data (option) delete tempPtr; // step IV: recycle return true; // delete successful } Question: what if I don’t do step I?

13 13 firstPtrlastPtr 7953 removeFromFront tempPtr if ( isEmpty() ) // List is empty return false; // delete unsuccessful else { Node *tempPtr = firstPtr; // step I if ( firstPtr == lastPtr ) firstPtr = lastPtr = 0; else firstPtr = firstPtr->nextPtr; // step II value = tempPtr->data; // step III: data being removed delete tempPtr; // step IV return true; // delete successful }

14 14 bool List::removeFromBack( int & value) { if ( isEmpty() ) return false; // delete unsuccessful else { Node *tempPtr = lastPtr; // step I: remember what to delete if ( firstPtr == lastPtr ) // trivial case firstPtr = lastPtr = 0; else { // non-trivial case Node *currentPtr = firstPtr; // step II: find “next to last” while ( currentPtr->nextPtr != lastPtr ) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; // step III: currentPtr->nextPtr = 0; // step IV: “housekeeping” } value = tempPtr->data; // step V: retrieve data deleted delete tempPtr; // step VI: recycle return true; // delete successful } Note: The most important part is step II.

15 15 removeFromBack firstPtrlastPtr 7953 tempPtrcurPtr if ( isEmpty() ) return false; // delete unsuccessful else { Node *tempPtr = lastPtr; if ( firstPtr == lastPtr ) firstPtr = lastPtr = 0; else { Node *currentPtr = firstPtr; while ( currentPtr->nextPtr != lastPtr ) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; // delete successful }

16 16 Questions How to delete the list? How do I know the length of the list? How to index? How can we search a node? How to insert a node in between?

17 17 Destructor Can we just ? List::~List() { delete firstPtr; }

18 18 curPtr 7953 Destruction tempPtr if ( !isEmpty() ) { // List is not empty Node *curPtr = firstPtr, *tempPtr; while ( curPtr != 0 ) { tempPtr = curPtr; curPtr = curPtr->nextPtr; delete tempPtr; }

19 19 List::~List() { if ( !isEmpty() ) { // List is not empty cout << "Destroying nodes...\n"; Node *currentPtr = firstPtr, *tempPtr; while ( currentPtr != 0 ) { // delete remaining nodes tempPtr = currentPtr; cout data << '\n'; currentPtr = currentPtr->nextPtr; delete tempPtr; } cout << "All nodes destroyed\n\n"; } ~List()

20 20 void main() { List mylist; instructions(); int choice, value; do { cout > choice; switch ( choice ) { case 1: cin >> value; mylist.insertAtFront( value ); mylist.print(); break; case 2: cin >> value; mylist.insertAtBack( value ); mylist.print(); break; case 3: if ( mylist.removeFromFront( value ) ) cout << value << " removed from list\n"; mylist.print(); break; case 4: if ( mylist.removeFromBack( value ) ) cout << value << " removed from list\n"; mylist.print(); break; } } while ( choice != 5 ); } void instructions() { cout << "Enter one of the following:\n" << " 1 to insert at beginning of list\n" << " 2 to insert at end of list\n" << " 3 to delete from beginning of list\n" << " 4 to delete from end of list\n" << " 5 to end list processing\n"; }

21 21 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 1 The list is: 1 ? 1 2 The list is: 2 1 ? 2 3 The list is: 2 1 3 ? 2 4 The list is: 2 1 3 4 ? 3 2 removed from list The list is: 1 3 4 ? 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

22 22 The Length? int List::Length( ) { int length = 0; Node *curPtr = firstPtr; while(curPtr != NULL){ length ++; curPtr = curPtr->nextPtr; } return length; }

23 23 Index the list? Node& List::Index(const int& index) { int count = index; Node *curPtr = firstPtr; Node *dPtr = NULL;// WHY? while(curPtr != NULL){ if (count == 0){ dPtr = curPtr; break; } count --; curPtr = curPtr->nextPtr; } if (dPtr == NULL)cout << “out of range!\n” ; return (*dPtr);// WHY? }

24 24 A more intuitive way Node& List::operator[](const int & index) { return Index(index); } Why don’t I overload an operator?

25 25 Search for a node? Give a specific data Want to check if the data is inside the list Return the address of the node if inside Return NULL otherwise

26 26 Search? Node& List::Search( const int& data) { Node *dPtr = 0; // NULL is 0 Node *curPtr = firstPtr; while(curPtr != NULL){ if ( curPtr->data == data){ cout << “found!” << endl; dPtr = curPtr; break; } curPtr = curPtr->nextPtr; } return (*dPtr); }

27 27 Insert in between? Given: –A piece of data –A position of the list Insert the data after the position of the list

28 28 bool List::insertAfter(const int& data, const int& pos) { Node* curPtr = & (Index(pos)); if (!curPtr){ cout << “Error: insertAfter\n”; return false; } else{ Node* newPtr = getNewNode(data); Node* nPtr = curPtr->nextPtr; curPtr->nextPtr = newPtr; newPtr->nextPtr = nPtr; if ( nPtr == NULL) // i.e., curPtr is the last one lastPtr = newPtr; return true; } Insert? Note: this one has several very good ideas, please study hard on this function!

29 29 void main() { List mylist; instructions(); int choice, value, pos; Node *dPtr; do { cout << "? "; cin >> choice; switch ( choice ) { case 1: cin >> value; mylist.insertAtFront( value ); mylist.print(); break; case 2: cin >> value; mylist.insertAtBack( value ); mylist.print(); break; case 3: if ( mylist.removeFromFront( value ) ) cout << value << " removed from list\n"; mylist.print(); break;

30 30 case 4: if ( mylist.removeFromBack( value ) ) cout << value << " removed from list\n"; mylist.print(); break; case 5: cin >> value; dPtr = &mylist.Search( value); if (dPtr) cout getData() << " found in the list\n"; else cout << value << " is not inside the list\n"; break; case 6: cin >> pos; // for indexing dPtr = &mylist[pos]; if(dPtr) cout << "List["<<pos<<"]="<< mylist[pos].getData() << endl; else out << "wrong!" << endl; break;

31 31 case 7: cin >> value >> pos; if (mylist.insertAfter(value, pos)){ cout << "insert " << value << " after " << pos << " done\n"; mylist.print(); } else cout << "can not be insert!\n"; break; default: break; } } while ( choice != 8 ); }

32 32 Summary What motivates the use of linked list? What defines a Node? What is a List? How to destruct a list? How to search a list? How to insert data into a list?

33 33 Question to think about What if I want a list for other data types?


Download ppt "1 Linked List (II) Ying Wu Electrical Engineering & Computer Science Northwestern University EECS 230 Lectures Series."

Similar presentations


Ads by Google