400 likes | 522 Views
Lists. Chapter 8. Linked Lists. As an ADT, a list is finite sequence (possibly empty) of elements Operations commonly include: Construction Allocate & initialize object Empty Check if it is empty Traverse Go through list, process elements in order stored
E N D
Lists Chapter 8
Linked Lists • As an ADT, a list is • finite sequence (possibly empty) of elements Operations commonly include: • Construction Allocate & initialize object • Empty Check if it is empty • Traverse Go through list, process elements in order stored • Insert Add an item to list at any point • Delete Remove an item from the list at any point
Array/Vector Implementation of List • Data Members: • Store the list items in consecutive array or vector locations a1, a2, a3 , . . . an a[0] a[1] a[2] ... a[n-1], a[n] ... a[CAPACITY-1] For an array, add a mySize member to store the length (n) of the list.
Array/Vector Implementation of List Operations Construction: Set mySize to 0; if run-time array, allocate memory for it For vector: let its constructor do the work Empty: mySize == 0 For vector: Use its empty() operation
Array/Vector Implementation of List Traverse: or for (int i = 0; i < size; i++) { Process(a[i]); } i = 0;while (i < size){ Process(a[i]); i++; }
Array/Vector Implementation of List • Insert: • Delete Insert 6 after 5 in 3, 5, 8, 9, 10, 12, 13, 15 3, 5, 6, 8, 9, 10, 12, 13, 15 Have to shift array elements to make room. Delete 5 from 3, 5, 6. 8, 9, 10, 12, 13, 15 3, 6, 8, 9, 10, 12, 13, 15 Have to shift array elements to close the gap.
Array/Vector Implementation of List • This implementation of lists is inefficient for dynamic lists • Those that change frequently • Those with many insertions and deletions So … We look for an alternative implementation.
Linked List For the array/vector-based implementation: • First element is at location 0 • Successor of item at location i is at location i + 1 • End is at location size – 1 Fix: • Remove requirement that list elements be stored in consecutive location. • But then need a "link" that connects each element to its successor Linked Lists !!
Linked Lists • Definition <=> A linked list of self-referential class objects • called nodes • connected by pointer links (thus, a "linked" list) • Subsequent nodes accessed via link-pointer member stored in each member • Link pointer in last node set to null (zero) • marks the end of the list • Nodes created dynamically, as needed
Self-Referential Classes • A self-referential class contains a pointer member that points to a class object of the same class type class Part_node { public: Part_node ( ); … private: char part_num[8], descrip[20]; int qty; float price; Part_node *next_part; } ;
NullPointer Pointervariable Link PointerMember Self-Referential Classes • This pointer to an object of the type being declared enables class objects to be linked together in various ways • This is how we get linked lists 0
Creates thenew pointer Allocates the space fora new part node Dynamic Memory Allocation • If the data structures are to be dynamic, then dynamic memory allocation is required • operators new and delete are essential part_node *newPtr = new part_node; 0
0 Dynamic Memory Allocation • The delete operator deallocates memory allocated with the new • Note: newPtr is not itself deleted -- rather the space newPtr points to delete newPtr;
Linked Lists Operations • Construction: first = null_value; • Empty: first == null_value? • Traverse ptr = first; while (ptr != null_value) { Process data part of node pointed to by ptr ptr = next part of node pointed to by ptr; }
Traverse ptr = first; while (ptr != null_value) { Process data part of node pointed to by ptr; ptr = next part of node pointed to by ptr; }
predptr 20 newptr Operations: Insertion 9 17 26 34 22 first • Insertion • To insert 20 after 17 • Need address of item before point of insertion • predptr points to the node containing 17 • Get a new node pointed to by newptr and store 20 in it • Set the next pointer of this new node equal to the next pointer in its predecessor, thus making it point to its successor. • Reset the next pointer of its predecessor to point to this new node And voila! The node is inserted (linked) into the list
Operations: Insertion • Note: insertion also works at end of list • pointer member of new node set to null • Insertion at the beginning of the list • predptr must be set to first • pointer member of newptr set to that value • first set to value of newptr Note: In all cases,no shifting of list elements is required !
predptr To free space Operations: Deletion ptr • Delete node containing 22 from list. • Suppose ptr points to the node to be deleted • predptr points to its predecessor (the 20) • Do a bypass operation: • Set the next pointer in the predecessor to point to the successor of the node to be deleted • Deallocate the node being deleted. 5 9 17 20 22 29 34 first
Linked Lists - Advantages • Access any item as long as external link to first item maintained • Insert new item without shifting • Delete existing item without shifting • Can expand/contract as necessary
Linked Lists - Disadvantages • Overhead of links: • used only internally, pure overhead • If dynamic, must provide • destructor • copy constructor • No longer have direct access to each element of the list • Many sorting algorithms need direct access • Binary search needs direct access • O(1) access becomes O(n) access • must go through first element, and then second, and then third, etc.
This is the inefficient part Linked Lists - Disadvantages • List-processing algorithms that require fast access to each element cannot be done as efficiently with linked lists. • Consider adding an element at the end of the list
Using C++ Pointers and Classes • To Implement Nodes class Node{ public: DataType data; Node * next;}; • Note: The definition of a Node is recursive • (or self-referential) • It uses the name Node in its definition • The next member is defined as a pointer to a Node
Working with Nodes • Declaring pointersNode * ptr;or typedef Node * NodePointer; NodePointer ptr; • Allocate and deallocateptr = new Node; delete ptr; • Access the data and next part of node(*ptr).data and (*ptr).nextor ptr->data and ptr->next
Working with Nodes class Node{ public: DataType data; Node * next; }; • Note data members are public • This class declaration will be placed inside another class declaration for LinkedList • The data members data and next of struct Node will be public inside the class • will accessible to the member and friend functions • will be private outside the class
Class Template LinkedList template <typename DataType>;class LinkedList{ private: class Node { public: DataType data; Node * next; }; typedef Node * NodePointer; . . .}; data is public inside class Node class Node is private inside LinkedList
first 9 17 22 26 34 Data Members for LinkedList • A linked list will be characterized by: • A pointer to the first node in the list. • Each node contains a pointer to the next node in the list • The last node contains a null pointer • As a variation first may • be a structure • also contain a count of the elements in the list
L first mySize 0 Function Members for LinkedList • Constructor • Make first a null pointer and • set mySize to 0 • Destructor • Nodes are dynamically allocated by new • Default destructor will not specify the delete • All the nodes from that point on would be "marooned memory" • A destructor must be explicitly implemented to do the delete
9 17 22 26 34 Function Members for LinkedList L 9 17 22 26 34 first • Copy constructor • By default, when a copy is made of a LinkedList object, it only gets the head pointer • Copy constructor will make a new linked list of nodes to which copyOfL will point mySize 5 copyOfL first mySize 5
prev L last 9 17 22 26 34 first mySize next 5 Variations • An empty head node • Every node has a predecessor • Does away with special case insertions • An empty trailer node • Every node has a successor • Doubly linked list
The STL list<T> Class Template • A sequential container • Optimized for insertion and erasure at arbitrary points in the sequence. • Implemented as a circular doubly-linked list with head node.
The STL list<T> Class Template Node structure struct list_node { pointer next, prev; T data; }
The STL list<T> Class Template • But it's allo/deallo-cation scheme is complex • Does not simply using new and delete operations. • Using the heap manager is inefficient for large numbers of allo/deallo-cations • Thus it does it's own memory management.
The STL list<T> Memory Management When a node is allocated • If there is a node on the free list, allocate it. • This is maintained as a linked stack • If the free list is empty: • Call the heap manager to allocate a block of memory (a "buffer", typically 4K) • Carve it up into pieces of size required for a node of a list<T>.
The STL list<T> Memory Management • When a node is deallocated • Push it onto the free list. • When all lists of this type T have been destroyed • Return it to the heap
PropertyArray vector<T> deque<T> list<T> Direct/random access ([]) + (exclnt) + (good)X Sequential access + + + Insert/delete at front -(poor) - + + Insert/delete at end + + + + Insert/delete in middle - - - + Overhead lowest low low/medium high Comparing List<t> With Other Containers • Note : list<T> does not support direct access • does not have the subscript operator [ ].
list<t>Iterators • list<T>'s iterator is "weaker" than that for vector<T>. • vector<T>: random access iterators • list<T>: bidirectional iterators • Operations in common • ++Move iterator to next element (like ptr = ptr-> next) • -- Move iterator to preceding element (like ptr = ptr-> prev) • * dereferencing operator (likeptr-> data)
list<t>Iterators • Operators in common • = assignment (for same type iterators) it1 = it2 makes it1 positioned at same element as it2 • == and != (for same type iterators) checks whether iterators are positioned at the same element
Using list<t>Iterators Example: Construct a list containing first 4 even integers; then output the list. list<int> l; for (int i = 1; i <= 4; i++) l.push_back(2*i); for (list<int>::iterator it = l.begin(); it != l.end(); it++) cout << *it << " "; cout << endl;
Limitations of list<t>Iterators • Directional iterators don't have:+, -, +=, -=, [] • list<t> iterators cannot do "jumping" • Noiterator ± n • No direct access • Result, cannot implement some sort() algorithms • Solution: list<T> has it's own sort() operation
Basic list<t>Operations • See page 451,2 • Constructors • Destructors • Empty, Size • Push, insert, pop, remove • Front, back • Iterator functions: • begin, end, • Sort • Merge, splice • Comparisons