200 likes | 333 Views
List Implementation. Circular, Doubly-Linked Lists Node Composition List Class Pushing and Popping Values Insert and Erase at Arbitrary Locations. Circular, Doubly-Linked Lists. STL list implemented using circular, doubly-linked list (& header node). No data field in header.
E N D
List Implementation • Circular, Doubly-Linked Lists • Node Composition • List Class • Pushing and Popping Values • Insert and Erase at Arbitrary Locations
Circular, Doubly-Linked Lists • STL list implemented using circular, doubly-linked list (& header node) No data field in header int A[ ] = { 4, 9, 3, 2 }; list<int> myList (A, A + 4);
Building Lists • Three constructors (a) list<double> reals (8); 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 (b) list <time24> times (6, time24 (8, 30)); 8:30 8:30 8:30 8:30 8:30 8:30 (c) list<string> types (strArr, strArr + 3); array vector list
list (); Create an empty list. This is the default constructor. CLASS list <list> Constructors list (size_t n, const T& value = T()); Create a list with n elements, each having a specified value. If the value argument is omitted, the elements are filled with the default value for type T. Type T must have a default constructor, and the default value of type T is specified by the notation T(). list (InIter first, InIter last); Initialize the list, using the range [first, last).
Iterators • To insert to or remove from middle of vector/list • Keeps track of current position in a vector/list • Can also be used to traverse a vector/list
Traversing a Vector Consider: for (int i = 0; i != v.size(); ++i) cout << v[i] << endl; for (vector<int>::iterator itr = v.begin(); itr != v.end(); ++i) cout << itr.??? << endl;
*: Accesses the value of the item currently pointed to by the iterator. *iter; CLASS list::iterator <list> Operations ++: Moves the iterator to the next item in the list. iter++; ++ iter; // both pre and post --: Moves the iterator to the previous item in the list. iter--; --iter; // both pre and post ==: Takes two iterators as operands and returns true when they both reference the same item in the list. iter1 == iter2 !=: Returns true when the two iterators do not reference the same item in the list. iter1 != iter2
Traversing a Vector Consider: for (int i = 0; i != v.size(); ++i) cout << v[i] << endl; for (vector<int>::iterator itr = v.begin(); itr != v.end(); ++i) cout << *itr << endl;
Traversing a Vector for (vector<int>::iterator itr = v.begin(); itr != v.end(); ++i) cout << *itr << endl; vector<int>::iterator itr = v.begin(); while(itr != v.end()) cout << *itr++ << endl; But why bother?
Operations Requiring Iterators • iterator insert(iterator pos, const Object & x) • iterator erase(iterator pos) • iterator erase(iterator start, iterator end)
List Insert list <int> li; // then populate list <int>::iterator newElt = li.insert (iter, 4);
List Erase list <int> li; // then populate list <int>::iterator i = li.erase (iter); cout << *i;
Ordered lists // Walk list to find insertion point list<int>::iterator curr; for (curr = lst.begin (); curr != lst.end () && item > *curr; ++cur) ; lst.insert (curr, item); What if inserting item = 83?
Node Composition struct Node { Node (const T& v = T (), Node* n = NULL, Node* p = NULL) : data (v), next (n), prev (p) { } T data; Node* next; Node* prev; };
List Class class List { // Insert Node struct def. Node* d; // ptr to dummy header size_t sz; // size public: List () : d (new Node ()), sz (0) { d->next = d->prev = d; } ~List () { while (! empty ()) pop_back (); delete d; } void push_front (const T& v); void push_back (const T& v); void pop_front (); void pop_back (); // Arbitrary location insert and erase };
Pushing a Value After insert : List with one element prev next header newNode
Pushing Values void push_front (const T& v) { Node* p = d; Node* s = d->next; Node* n; n = new Node (v, s, p); p->next = n; s->prev = n; ++sz; } void push_back (const T& v) { Node* p = d->prev; Node* s = d; Node* n; n = new Node (v, s, p); p->next = n; s->prev = n; ++sz; }
Inserting a Node Lobj.insert (curr, item); newNode = new Node (item, curr, prevNode); // 2 & 1 prevNode->next = newNode; // 3 curr->prev = newNode; // 4 ++sz;
Erasing a Node lObj.erase (curr); curr->prev->next = curr->next; // 1 curr->next->prev = curr->prev; // 2 delete curr; --sz;