590 likes | 894 Views
Linked List. Joe Meehean. Linked List. …. item N. phead :. item 1. Conceptual Picture N items chained together using pointers p ointed to by variable head Advantage allows list to grow indefinitely without copying constant time inserts and removes just (un)hook into/from chain.
E N D
Linked List Joe Meehean
Linked List … item N phead: item 1 • Conceptual Picture • N items • chained together using pointers • pointed to by variable head • Advantage • allows list to grow indefinitely without copying • constant time inserts and removes • just (un)hook into/from chain
List Node item 1 • Private nested class • nested class: class defined within a class • private nested: not visible outside outer class • Member variables • public: • T data; • Node<T> *next; • Constructor • Node( const T& data = T(), Node<T>* n = NULL)
Connecting List Nodes Node<string>* head; phead: head = new Node<string>(“ant”); ant phead: head->next = new Node<string>(“bat”); bat ant phead:
DISCUSSION BREAK!!! bat phead: ant cat n: • Given head and a pointer n • What expression gets node containing: • ant • bat • cat
DISCUSSION BREAK!!! bat phead: ant cat n: • Given head and a pointer n • What expression gets node containing: • ant => *head • bat => *(head->next), *n • cat => *(head->next->next), *(n->next)
Inserting Nodes tmp: jar phead: cat bat ant n:
Inserting Nodes tmp: jar phead: cat bat ant n:
Inserting Nodes tmp: jar phead: cat bat ant n:
Removing Nodes n: jar phead: cat bat ant
Removing Nodes n: jar phead: cat bat ant
Using Nodes to make a List • LCLinkedList<T> • Member Variables • intnumItems; • Node<T>* phead; • Methods • same ADT as ArrayList • also has push_front, pop_front • same public methods
push_front phead: cat bat tmp: ant
push_front phead: cat bat tmp: ant
push_front phead: cat bat tmp: ant
push_front void push_front(const T& newItem){ Node* tmp = new Node(newItem); tmp->next = phead; phead = tmp; numItems++; }
push_back tmp: phead: cat bat ant
push_back tmp: phead: cat bat ant
push_back void push_back(const T& newItem){ // list is empty (special case) if( phead == NULL ){ phead = new Node(newItem); }else{ // find the end of the list Node* pNode = phead; while(pNode->next != NULL){ pNode = pNode->next; } // add the item pNode->next = new Node(newItem); // increment the count numItems++; }}
Recall: push_front void push_front(const T& newItem){ Node* tmp = new Node(newItem); tmp->next = phead; phead = tmp; numItems++; }
Recall: push_back void push_back(const T& newItem){ // list is empty (special case) if( phead == NULL ){ phead = new Node(newItem); }else{ // find the end of the list Node* pNode = phead; while(pNode->next != NULL){ pNode = pNode->next; } // add the item pNode->next = new Node(newItem); // increment the count numItems++; }}
Header Node phead: bat ant Header Eliminates special 1st node case for add and remove Create header at initialization Don’t count in size Ignore for contains
push_back (with header) void push_back(const T& newItem){ // find the end of the list Node* pNode = phead; while(pNode->next != NULL){ pNode = pNode->next; } // add the item pNode->next = new Node(newItem); // increment the count numItems++; }
DISCUSSION BREAK!!! • Can you modify LCLinkedList to push_back(…) in O(1)? • Hint: You can add member variables
Tail Pointer ptail: phead: bat ant Header push_back now constant time but, we must update tail pointer when adding to end
Tail Pointer ptail: phead: Header tail pointer points at header if list is empty
pop_back() ptail: phead: bat ant Header
pop_back() phead: ptail: bat ant Header
pop_back(with header and tail pointer) void pop_back(){ if( phead != ptail ){ // find the node just before ptail Node* pNode = phead; while(pNode->next != ptail){ pNode= pNode->next; } // remove the node pNode->next = NULL; ptail = pNode; // decrement the count numItems--; } }
pop_back() ptail: phead: bat ant Header Tail pointer close to the right position Still must iterate over nearly entire list Can we make remove at end O(1)?
DISCUSSION BREAK!!! • Can you modify LCLinkedList to pop_back() in O(1)? • Hint: You can modify the structure of the list
Doubly Linked List ptail: phead: ant bat Header • Node • Member variables • public: • T data; • Node<T> *next; • Node<T> *prev
Tail Node ptail: phead: Tail bat Header • Tail node • removes special cases just like header node • tail and header node called sentinels
pop_back() phead: ptail: Tail bat Header
pop_back() phead: ptail: Tail bat Header
pop_back() phead: ptail: Tail bat Header
pop_back(doubly linked with sentinels) void pop_back(){ if( phead->next != ptail ){ ptail->prev = ptail->prev->prev; ptail->prev->next = ptail; // decrement the count numItems--; } }
Linked Lists vs Array Lists • Space • linked needs two extra pointers per entry • linked needs two extra nodes • array may be up to N/2-1 too large • array may be way too big if some elements removed • array better small data items (e.g., ints) • linked way better for big items (e.g., classes) • too close to call for medium items (e.g., 3 ints)
Linked Lists vs Array Lists • Ease implementation • fairly close • linked list has more special cases and work-arounds for special cases
Expanding List Functionality • What if we want to remove an item from the middle of a linked list? • remove at i • traverse list from beginning until we reach i • fix up the pointers • O(N)
Expanding List Functionality • What if we were already moving through the list? • e.g., remove all even numbers • if we did this internally (inside the list class),we would have a pointer to the node to remove • O(1)
Linked List Iterators • LCList::Iterator • Public nested class in LCList • Member data • Node<T> * currNode; • Friends • LCList<T>
Linked List Iterator Iterator::Iterator() : currNode(NULL){} Iterator::Iterator(Node* pNode) : currNode(pNode){} void Iterator::operator ++(){ currNode = currNode->next; } void Iterator::operator –-(){ currNode = currNode->prev; } T& Iterator::operator *(){ return currNode->data; }
Linked List Iterator Iterator LCList::begin(){ return Iterator(phead->next); } Iterator LCList::end(){ return Iterator(ptail); }
remove(Iterator) phead: Head bat cat Tail rat ant ptail: iter:
remove(Iterator) phead: Head bat cat Tail rat ant ptail: iter:
remove(Iterator) phead: Head bat cat Tail rat ant ptail: iter: