290 likes | 297 Views
Linked Lists. Chapter 4. Basic Linked List Node. struct Node { char m_item; Node * m_next; }; typedef Node * ptrType; //or struct Node; //forward declaration typedef Node * PtrType; typedef char ItemType; struct Node { ItemType m_item; PtrType m_next; };.
E N D
Linked Lists Chapter 4
Basic Linked List Node struct Node { char m_item; Node * m_next; }; typedef Node * ptrType; //or struct Node; //forward declaration typedef Node * PtrType; typedef char ItemType; struct Node { ItemType m_item; PtrType m_next; }; CSCD 326
Pointer to the Head of a List • For any given linked list, you need something that will ALWAYS point at the beginning of the list. • To accomplish this you need a pointer to a node. • Some implementations of linked lists involve a “dummy node” that the head of the list always points at. This simplifies some operations where you have to watch out for and empty list (insert and delete operations). CSCD 326
LinkedList.h //*********************************************** // Header file LinkedList.h for the ADT list. // Pointer-based implementation. //*********************************************** #include <stddef.h> // for NULL #include <assert.h> // for assert() struct listNode; // linked list node typedef listNode* ptrType; // pointer to node typedef char listItemType; //could be any type! struct listNode // a node on the list { listItemType Item; // a data item on the list ptrType Next; // pointer to next node }; // end struct CSCD 326
LinkedList.h continued class listClass { public: // constructors and destructor: listClass(); //default constructor listClass(const listClass& L); // copy constructor ~listClass(); // destructor // list operations: bool ListIsEmpty() const; int ListLength() const; void ListInsert(int NewPosition, listItemType NewItem,bool& Success); void ListDelete(int Position, bool& Success); void ListRetrieve(int Position, listItemType& DataItem, bool& Success) const; CSCD 326
LinkedList.h continued private: int Size; // number of items in list ptrType Head; // pointer to linked list of items ptrType PtrTo(int Position) const; // Returns a pointer to the Position-th node // in the linked list. }; // end class // End of header file. CSCD 326
LinkedList.cpp //*********************************************** //Implementation file ListP.cpp for the ADT list. // Pointer-based implementation. //*********************************************** #include "ListP.h" // header file listClass::listClass(): Size(0), Head(NULL) { } // end default constructor CSCD 326
LinkedList.cpp continued listClass::listClass(const listClass& L): Size(L.Size) { if (L.Head == NULL) Head = NULL; // original list is empty else { // copy first node Head = new listNode; assert(Head != NULL); // check allocation Head->Item = L.Head->Item; // copy rest of list ptrType NewPtr = Head; // new list pointer // NewPtr points to last node in new list // OrigPtr points to nodes in original list CSCD 326
LinkedList.cpp continued for (ptrType OrigPtr = L.Head->Next; OrigPtr != NULL; OrigPtr = OrigPtr->Next) { NewPtr->Next = new listNode; assert(NewPtr->Next != NULL); NewPtr = NewPtr->Next; NewPtr->Item = OrigPtr->Item; } // end for NewPtr->Next = NULL; } // end if } // end copy constructor CSCD 326
LinkedList.cpp continued listClass::~listClass() { bool Success; while (!ListIsEmpty()) ListDelete(1, Success); } // end destructor bool listClass::ListIsEmpty() const { return bool(Size == 0); } // end ListIsEmpty int listClass::ListLength() const { return Size; } // end ListLength CSCD 326
LinkedList.cpp continued ptrType listClass::PtrTo(int Position) const // -------------------------------------------------- // Locates a specified node in a linked list. // Precondition: Position is the number of the // desired node. // Postcondition: Returns a pointer to the desired // node. If Position < 1 or Position > the number of // nodes in the list, returns NULL. // -------------------------------------------------- { if ( (Position < 1) || (Position > ListLength()) ) return NULL; else // count from the beginning of the list { ptrType Cur = Head; for (int Skip = 1; Skip < Position; ++Skip) Cur = Cur->Next; return Cur; } // end if } // end PtrTo CSCD 326
LinkedList.cpp continued void listClass::ListRetrieve(int Position, listItemType& DataItem,bool& Success) const { Success = bool( (Position >= 1) && (Position <= ListLength()) ); if (Success) { // get pointer to node, then data in node ptrType Cur = PtrTo(Position); DataItem = Cur->Item; } // end if } // end ListRetrieve CSCD 326
LinkedList.cpp continued void listClass::ListInsert(int NewPosition, listItemType NewItem, bool& Success) { int NewLength = ListLength() + 1; Success = bool( (NewPosition >= 1) && (NewPosition <= NewLength) ); if (Success) { // create new node and place NewItem in it ptrType NewPtr = new listNode; Success = bool(NewPtr != NULL); if (Success) { Size = NewLength; NewPtr->Item = NewItem; CSCD 326
LinkedList.cpp continued // attach new node to list if (NewPosition == 1) {//insert new node at beginning of list NewPtr->Next = Head; Head = NewPtr; } else { ptrType Prev = PtrTo(NewPosition-1); // insert new node after node // to which Prev points NewPtr->Next = Prev->Next; Prev->Next = NewPtr; } // end if } // end if } // end if } // end ListInsert CSCD 326
LinkedList.cpp continued void listClass::ListDelete(int Position, bool& Success) { ptrType Cur; Success = bool( (Position >= 1) && (Position <= ListLength()) ); if (Success) { --Size; if (Position == 1) { // delete the first node from the list Cur = Head; // save pointer to node Head = Head->Next; } CSCD 326
LinkedList.cpp continued else { ptrType Prev = PtrTo(Position-1); // delete the node after the // node to which Prev points Cur = Prev->Next;//save pointer to node Prev->Next = Cur->Next; } // end if // return node to system Cur->Next = NULL; delete Cur; Cur = NULL; } // end if } // end ListDelete CSCD 326
head cur A B C D tmp Insertion into a Linked List tmp = new ListNode; tmp->Element = ‘X’; tmp->Next = cur->Next; cur->Next = tmp; X struct ListNode { char Element; ListNode *Next; }; CSCD 326
Linked List Insertion - other methods • If ListNode has a constructor which initializes data elements directly the code becomes: tmp = new ListNode(‘X’, cur->next); cur->Next = tmp; • and tmp is actually no longer needed so the code becomes: cur->Next = new ListNode(‘X’, cur->next); CSCD 326
cur head A B C D tmp X Linked List Node Deletion ListNode *tmp = cur->Next; cur->Next = cur->Next->Next; delete tmp; CSCD 326
Insert and Delete operations on an empty list • One problem with the insertion and deletion methods is that they require special cases and different actions for first nodes • The addition of a dummy head node to the linked list eliminates the special cases • the header node does not contain any data and its pointer points to the first data containing node • an empty list now consists of a head pointer and a header node with a NULL pointer CSCD 326
Abstract Data Type List • We have been referring to linked lists with the name List • it is actually just one implementation of the higher object which is a General List • A General List could be implemented using arrays rather than linked lists • How would that implementation change from the linked list implementation? CSCD 326
Criteria for Linked Lists - ACIDS • One way to decide which General List implementation is better for a certain problem is a criterion based on General List operations • ACIDS test how easily are operations done • Add • Change • Inspect • Delete • Sort • Linked lists are better for adding or deleting items • Arrays are better for sorting or finding (inspect, change, delete) items CSCD 326
Big-O Notation • Algorithm Complexity (speed) - a method of comparing algorithm speeds is Big-O notation: • O(n) (where n is number of items in a list) - says number of operations in an algorithm is directly proportional to number of elements - linear time complexity • O(1) - says number of operations is constant and not a function of number of elements • Insertion and deletion in linked lists is O(1) while in array based lists it is O(n) - constant time complexity • since all n items might have to be moved CSCD 326
Doubly Linked Lists • Even though each node in a singly linked list has a well defined predecessor - it is impossible to move from a node to its predecessor • Doubly linked lists solve this problem by allowing movement in both directions through a list • This is accomplished by adding a pointer to each node which contains the address of the previous node CSCD 326
Doubly Linked List Implementation struct ListNode { char Element; ListNode *Next; ListNode *Prev; ListNode( ) : Next(NULL), Prev(NULL) { } ListNode( const char & C, ListNode *N = NULL, ListNode *P = NULL) : Element(C), Next(N), Prev(P){ } }; CSCD 326
A M Z tmp Doubly Linked List Insertion // inserting AFTER cur tmp = new ListNode(‘X’, cur->Next, cur); cur->Next->Prev = cur; cur->Next = tmp; cur X CSCD 326
A M Z cur Doubly Linked List Deletion // deleting cur cur->Next->Prev = cur->Prev; cur->Prev->Next = cur->Next; delete cur; CSCD 326
Header Nodes for DLL’s • Inserting /deleting first and last nodes are special cases for doubly linked lists • a single routine with no conditions can be used to insert into /delete from doubly linked lists by adding a dummy header node to both ends of the list CSCD 326
Circular Linked Lists • The last node in the list points to first • Usually no header node is used • A single node list points to itself • Problems can arise when traversing the list to its end - easy to construct an infinite loop A B C D CSCD 326