/
Two-Way Lists (Doubly Linked Lists) Let's encapsulate linked lists as Two-Way Lists (Doubly Linked Lists) Let's encapsulate linked lists as

Two-Way Lists (Doubly Linked Lists) Let's encapsulate linked lists as - PDF document

yoshiko-marsland
yoshiko-marsland . @yoshiko-marsland
Follow
393 views
Uploaded On 2016-03-17

Two-Way Lists (Doubly Linked Lists) Let's encapsulate linked lists as - PPT Presentation

class List List head new Node headnext headprev head destructor virtual List Node p headnext while p head Node next pnext delete p ID: 259284

class List

Share:

Link:

Embed:

Download Presentation from below link

Download Pdf The PPT/PDF document "Two-Way Lists (Doubly Linked Lists) Let'..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Two-Way Lists (Doubly Linked Lists) Let's encapsulate linked lists as we did the class. First we'll define a typical node in our Next we'll define a class that supports the following operations: // add two elements to the end of the list x.push_back(5); x.push_back(6); // output and delete list while (!x.empty()) { cout () x.pop_back(); } To support these operations we'll need a constructor, destructor, functions push_backbackpop_back, and empty class List { List() { head = new Node; ��head-next = head-prev = head; } // destructor virtual ~List() { �Node *p = head-next; while (p != head) { Node *next = �p-next; delete p; p = next; } delete head; } // insert value in back of list void push_back(double value) { Node *p = new Node; � p-value = value; �p-next = head; ��p-prev = head-prev; ��p-next-prev = p; ��p-prev-next = p; } // delete value from back of list void pop_back() { �Node *p = head-prev; ���p-prev-next = p-next; ���p-next-prev = p-prev; delete p; } // return value on back of list double back() const { ��return head-prev-value; } // return true if list is empty bool empty() const { �return head-next == head; } Unlike vectors, we can easily insert and delete elements from the front of a list. Let's implement functions push_frontpop_frontfront for this purpose x.push_front(5); x.push_front(6); // output and delete list while (!x.empty()) { cout () x.pop_front(); } These are easily implemented as follows: Node *p = new Node; &#x end;&#xl; 0;p-value = value; &#x end;&#xl; 0;&#x end;&#xl; 0;p-next = head-next; &#x end;&#xl; 0;p-prev = head; &#x end;&#xl; 0;&#x end;&#xl; 0;p-next-prev = p; &#x end;&#xl; 0;&#x end;&#xl; 0;p-prev-next = p; &#x end;&#xl; 0;Node *p = head-next; &#x end;&#xl; 0;&#x end;&#xl; 0;&#x end;&#xl; 0;p-prev-next = p-next; &#x end;&#xl; 0;&#x end;&#xl; 0;&#x end;&#xl; 0;p-next-prev = p-prev; delete p; &#x end;&#xl; 0;&#x end;&#xl; 0;return head-next-value; To delete all elements with a specific value we'll support a remove &#x end;&#xl; 0;Node *p = head-next; while (p != head) { &#x end;&#xl; 0;Node *next = p-next; &#x end;&#xl; 0;if (p-value == value) { &#x end;&#xl; 0;&#x end;&#xl; 0;&#x end;&#xl; 0;p-prev-next = p-next; &#x end;&#xl; 0;&#x end;&#xl; 0;&#x end;&#xl; 0;p-next-prev = p-prev; delete p; } p = next; } } Finally we'll implement a copy constructor and assignment operator. For convenience two static helper functions are defined that delete and copy lists. This also simplifies coding for the destructor since it can now call deleteList to delete the list. // delete list �Node *p = head-next; while (p != head) { �Node *next = p-next; delete p; p = next; } delete head; // create dummy header to = new Node; ��to-next = to-prev = to; // copy nodes ��for (Node *p = from-next; p != from; p = p-next) { Node *t = new Node; ��t-value = p-value; // insert at end of list �t-next = to; ��t-prev = to-prev; ��t-prev-next = t; ��t-next-prev = t; } deleteList(head); copyList(x.head, head); if (this == &x) return *this; deleteList(head); copyList(x.head, head); return *this; We'll implement an iterator similar to the one done for the class. In particular, we'll support Again, if we view the iterator as a pointer to an object in the collection (in this case, a pointer to the Node structure), we have the following equivalent code: &#x pos;&#x-000;cout To support this notion, let's define the following and member functions: &#x pos;&#x-000;return head-next; return head; We'll implement class ListIterator to define the iterator itself. To support the return values of and end we'll include a constructor in the ListIterator that converts "Node *" to a ListIterator // default constructor ListIterator() { i = 0; } // construct iterator for given pointer (used for begin/end) ListIterator(Node *p) { i = p; } Node *i; // current value of iterator Let's repeat the original examples that uses an iterator, and the corresponding example that uses pointers: &#x pos;&#x-000;cout We've defined a member function that returns &#x pos;&#x-000;head-next, and an member function that returns head. To assign one iterator to another, such as in the statement we'll rely on the default bitwise copy behavior of the assignment operator. To compare, increment, and dereference iterators, we'll add the following member functions to ListIterator // test two iterators for not equal bool operator!=(const ListIterator& x) const { return i != x.i; } // preincrement operator ListIterator& operator++() { &#x pos;&#x-000;i = i-next; return *this; } // return value associated with iterator double& operator*() const { &#x pos;&#x-000;return i-value; } Node *i; // current value of iterator Finally we'll implement an erase member function in the class. Function erase allows the user to delete any node using an iterator. The following code implements the erase member function in the class: For this to work the compiler must know how to convert an ListIterator, to a "Node *The following operator, in the class, will provi // convert iterator to Node* operator Node*() const { return i; } Node *i; // current value of iterator #include "List.h" &#xlist;// std: #include typedef List Data; oub;&#xle00;// std: typedef list //////////// // List.h // public: List& operator=(const List& x); void pop_back(); void remove(double value); }; struct Node { Node *prev; // previous node public: operator Node*() const { return i; } ////////////// // list.cpp // static void copyList(const Node *from, Node *&to) { // create dummy header �� t-prev-next = t; �� t-next-prev = t; �� head-next = head-prev = head; } // assignment operator List& List::operator=(const List& x) { Node *p = new Node; � p-value = value; delete p; } double List::front() const { �� return head-next-value; ��� p-next-prev = p-prev; delete p; // delete all nodes with specified value void List::remove(double value) { ��� p-next-prev = p-prev; delete p; List::iterator List::begin() const { � return head-next;