1.23k likes | 1.24k Views
CH4. LINKED LISTS. 4.1 Singly Linked Lists. Sequential representation successive nodes of the data object are stored a fixed distance apart order of elements is the same as in ordered list adequate for functions such as accessing an arbitrary node in a table
E N D
4.1 Singly Linked Lists • Sequential representation • successive nodes of the data object are stored a fixed distance apart • order of elements is the same as in ordered list • adequate for functions such as accessing an arbitrary node in a table • operations such as insertion and deletion of arbitrary elements from ordered lists become expensive • Linked representation • successive items of a list may be placed anywhere in memory • order of elements need not be the same as order in list • each data item is associated with a pointer (link) to the next item
4.1 Singly Linked Lists(Cont’) • List of 3-letter words : (BAT, CAT, EAT, ..., VAT, WAT) data[8] = BAT first = 8 link[8] = 3 data[3] = CAT Figure 4.1: Nonsequential list representation
4.1 Singly Linked Lists(Cont’) first BAT CAT EAT WAT 0 Figure 4.2 : Usual way to draw a linked list
4.1 Singly Linked Lists(Cont’) • To insert GAT between FAT and HAT (1) get a node N that is currently unused ; let its address be x (2) set the data field of N to GAT (3) set the link field of N to point to the node after FAT, which contains HAT (4) set the link field of the node containing FAT to x
4.1 Singly Linked Lists(Cont’) Figure 4.3 : Inserting a node
4.1 Singly Linked Lists(Cont’) • To delete GAT • find the element that immediately precedes GAT, which is FAT • set the link field of FAT to the position of HAT first BAT CAT EAT FAT GAT HAT WAT 0 Figure 4.4 : Delete GAT from list Note : must know the previous element
4.2 Representing Lists in C++ 4.2.1 Defining A List Node in C++ • Defining a List Node in C++ • Class definition for 3-letter node • A more complicated list structure class ThreeLetterNode{private: char data[3]; ThreeLetterNode *link; }; class nodea{ private: int data1; char data2; float data3; nodea *linka; nodeb *linkb; }; class nodeb{ private: int data; nodeb *link; };
4.2 Representing Lists in C++(Cont’) 22 data data1 5.5 link data2 ‘c’ data3 3.14 linka linkb nodeb nodea Figure 4.5 : Illustration of the node structures nodea and nodeb
4.2 Representing Lists in C++(Cont’) 4.2.2 Designing a list in C++ • Design approach • use a class ThreeLetterList corresponding to the entire list data structure • ThreeLetterList supports member functions for list manipulation operations • use a composite of two classes, ThreeLetterNode and ThreeLetterList • ThreeLetterList HAS-A ThreeLetterNode • Definition • a data object of type A HAS-A data object of type B if A conceptually contains B
4.2 Representing Lists in C++(Cont’) Figure 4.6 : Referencing the data members of a node
4.2 Representing Lists in C++(Cont’) ThreeLetter List ThreeLetter Node first CAT EAT WAT 0 Figure 4.7 : Conceptual relationship between ThreeLetterList and ThreeLetterNode
4.2 Representing Lists in C++(Cont’) • ThreeLetterList • contains only the pointer first • declare to be a friend of ThreeLetterNode • only member functions of ThreeLetterList and ThreeLetterNode can access the private members of ThreeLetterNode • only list manipulation operations have access to data members of ThreeLetterNode ThreeLetter List ThreeLetter Node first BAT CAT WAT 0 Figure 4.8 : Actual relationship between ThreeLetterList and ThreeLetterNode
4.2 Representing Lists in C++(Cont’) class ThreeLetterList; // forward declaration class ThreeLetterNode{friend class ThreeLetterList;private: char data[3]; ThreeLetterNode *link;}; class ThreeLetterList{public: // List Manipulation operations…private: ThreeLetterNode *first;}; Program 4.1 : Composite classes
4.2 Representing Lists in C++(Cont’) • Nested Classes • one class is defined inside the definition of another class • ThreeLetterNode objects (private) cannot be accessed outside class ThreeLetterList • ThreeLetterNode data members are public, so they can be accessed by member functions of ThreeLetterList
4.2 Representing Lists in C++(Cont’) class ThreeLetterList{public: // List Manipulation operations…. private: class ThreeLetterNode{ // nested class public: char data[3]; ThreeLetterNode *link; }; ThreeLetterNode *first;}; Program 4.2 : Nested classes
4.2 Representing Lists in C++(Cont’) • Using composite classes, the node class can be used by two data structures
4.2 Representing Lists in C++(Cont’) 4.2.3 Pointer Manipulation in C++ • new command • delete command • null command • ThreeLetterNode* f; • nodea* y; • nodeb* z; • f = new ThreeLetterNode; • y = new nodea; • z = new nodeb; • *f : the node of type ThreeLetterNode delete f; delete y; delete z; constant 0
4.2 Representing Lists in C++(Cont’) x a a b x y b b b y (a) (b) x=y (c) *x=*y Figure 4.9 : Effect of pointer assignments
4.2 Representing Lists in C++(Cont’) 4.2.4 List Manipulation Operations class List {private: ListNode *first;public: .... }; class ListNode {friend class List;private: int data; ListNode *link; };
4.2 Representing Lists in C++(Cont’) void List::Create2(){ first = new ListNode(10); // create and initialize first node // create and initialize second node and place its address in first→link first→link = new ListNode(20);} ListNode::ListNode(int element = 0) // 0 is the default argument // in constructor for List Node{ data = element; link = 0; // null pointer constant} Program 4.3 : Creating a two-node list
4.2 Representing Lists in C++(Cont’) first 10 20 0 Figure 4.10 : A two-node list
4.2 Representing Lists in C++(Cont’) • Example void List::Insert50(ListNode *x) { //insert new node after x ListNode *t = new ListNode(50); //create and initialize new node if(!first) //insert into empty list { first = t; return; //exit List::Insert50 } //insert after x t->link = x->link; x->link = t;} Program 4.4 : Inserting a node
4.2 Representing Lists in C++(Cont’) first first x 50 0 0 t t 50 (a) (b) Figure 4.11 : Inserting into an empty and nonempty list
4.2 Representing Lists in C++(Cont’) Void List::Delete(ListNode *x, ListNode *y){ // delete x placed after y if(!y) first = first->link; else y->link = x->link; delete x; // return the node} Program 4.5 : Deleting a node x first y x first
4.2 Representing Lists in C++(Cont’) Figure 4.12 : Possible configuration for a singly linked list traversed in both directions
4.3 A Reusable Linked List Class 4.3.1 Implementing Linked Lists with Templates • Implementing Linked Lists with Templates • Linked-list • a container class • good for implementation with templates • an empty linked list of integers intlist List<int> intlist;
4.3 A Reusable Linked List Class(Cont’) template <class Type> class List; // forward declaration template <class Type>class ListNode{ friend class List<Type>;private: Type data; ListNode *link;}; template <class Type>class List{public: List() first = 0;; // constructor initializing first to 0 // List manipulation operations…. private: ListNode<Type> *first;}; Program 4.6 : Template definition of linked lists
4.3 A Reusable Linked List Class(Cont’) 4.3.2 Linked Lists Iterators • Iterator • an object that is used to traverse all the elements of a container class • Example operations on an integer container class C • print all integers in C • obtain the max, min, mean, median, or mode of all integers in C • obtain the sum or product of all integers in C • Pseudo-code for the operations initialization step;for each item in C { current=current item of C; body;}postprocessing step;
4.3 A Reusable Linked List Class(Cont’) int x = -MAXINT; // initialization statement for each item in C { current = current item of C; x = max(current, x); // body } return x; // postprocessing step Program 4.7 : Pseudo-code for computing maximum element
4.3 A Reusable Linked List Class(Cont’) • All operations have to be implemented as member functions of a particular container class • drawbacks • many operations do not make sense to certain object types • too many operations in a class • users have to learn how to traverse the container class • ListIterator<Type> • handles details of the linked list traversal • retrieves elements stored in the list
4.3 A Reusable Linked List Class(Cont’) enum Boolean { FALSE, TRUE};template <class Type> class List;template <class Type> class ListIterator; template <class Type> class ListNode{ friend class List<Type>; friend class ListIterator<Type>;private: Type data; ListNode *link;}; template <class Type> class List{ friend class ListIterator<Type>;public: List() {first = 0;}; // List manipulation operations … private: ListNode<Type> *first; }; list first
4.3 A Reusable Linked List Class(Cont’) template <class Type> class ListIterator{ public: ListIterator(const List<Type> &l): list(l), current(l.first) {}; Boolean NotNull(); Boolean NextNotNull(); Type* First(); Type* Next(); private: const List<Type> &list; // refers to an existing list ListNode<Type> *current; // points to a node in list }; Program 4.8 : Template definition of linked lists
4.3 A Reusable Linked List Class(Cont’) template <class Type> // check that the current element in list is non-null Boolean ListIterator<Type>::NotNull(){ if(current) return TRUE; else return FALSE;} template <class Type> //check that the next element in list is non-null Boolean ListIterator<Type>::NextNotNull(){ if(current && current->link) return TRUE; else return FALSE;}
4.3 A Reusable Linked List Class(Cont’) template <class Type> // return a pointer to the first element of listType* ListIterator<Type>::First(){ if(list.first) return &list.first->data; else return 0;} template <class Type> // return a pointer to the next element of listType* ListIterator<Type>::Next(){ if(current){ current = current->link; if (current) return ¤t->data; } else return 0;} Program 4.9 : List iterator functions
4.3 A Reusable Linked List Class(Cont’) int sum(const List<int>& l){ Listiterator<int> li(l); // li is associated with list l if(!li.NotNull()) return 0; // empty list, return 0 int retvalue = *li.First(); // get first element while(li.NextNotNull()) // make sure that next element exists retvalue += *li.Next(); // get it, add it to the current total return retvalue; } Program 4.10 : Using iterators to compute the sum of elements
4.3 A Reusable Linked List Class(Cont’) • Function sum does not require access to the private data members of List<Type> or List node<Type> Listlterator current List List ListNode first
4.3 A Reusable Linked List Class(Cont’) 4.3.3 Linked List Operations • Operations included in most reusable classes • constructors (including default and copy constructors) • a destructor • operator= • operator== • operators to input and output a class object (by overloading operator>> and operator<<) • Operations in a linked list class • insertion, deletion, other manipulations • last : a private data member in List<Type>
4.3 A Reusable Linked List Class(Cont’) template<class Type> void List<Type>::Attach(Type k){ ListNode<Type>* newnode = new ListNode<Type>(k); if ( first==0 ) first = last = newnode; else { last->link = newnode; last = newnode; } } Program 4.11 : Attaching a node to the end of a list
4.3 A Reusable Linked List Class(Cont’) template <class Type>void List<Type>::Invert() // A chain x is inverted so that if x = (a1, ..., an), // then, after execution, x = (an, ..., a1).{ ListNode<Type> *p = first, *q = 0; // q trails p while(p){ ListNode<Type> *r = q; q = p; // r trails q p = p->link; // p moves to next node q->link = r; // link q to preceding node } first = q;} Program 4.12 : Inverting a list
4.3 A Reusable Linked List Class(Cont’) 1 st iteration q p 2 nd iteration r q p
4.3 A Reusable Linked List Class(Cont’) template <class Type> void List<Type>::Concatenate(List<Type>b) // this = (a1, ..., am) and b = (b1, ..., bn), m, n≥0 // produces the new chain z = (a1, ..., am, b1, ..., bn) in this. { if (!first) { first = b.first; return; } if (b.first) { for (ListNode<Type> *p = first; p->link; p = p->link); // no body p->link = b.first; } } Program 4.13 : Concatenating two chains
4.4 Circular Lists • Circular list • link field of the last node points to the first node in the list • to check whether current points to the last node: current→link==first first BAT CAT WAT EAT Figure 4.13 : A circular list
4.4 Circular Lists(Cont’) first x1 x2 x3 Data link Figure 4.14 : Example of a circular list last x1 x2 x3 Data link Figure 4.15 : Pointing to the last node of a circular list
4.4 Circular Lists(Cont’) template <class Type> void CircList::InsertFront(ListNode <Type> *x) // Insert the node pointed at by x at the "front" of the circular // list this, where last points to the last node in the list. { if(!last){ // empty list last = x; x->link = x; } else { x->link = last->link; last->link = x; } } Program 4.14 : Inserting at the front
4.4 Circular Lists(Cont’) • last : the private data member that points to the last node • a dummy head node : to avoid a case in which the empty list is handled specially first (a) first BAT CAT EAT WAT (b) Figure 4.16 : A circular list with a head node
4.5 Linked Stacks and Queues Figure 4.17 : Linked stack and queue
4.5 Linked Stacks and Queues(Cont’) class Stack; // forward declaration class StackNode { friend class Stack; private: int data; StackNode *link; StackNode(int d=0, StackNode *l=0): data(d), link(l) {}; // condtructor }; class Stack { public: Stack() {top=0;}; // constructor void Add(condt int); int* Delete(int&); private: StackNode *top; void StackEmpty(); }; Program 4.15 : Stack class definition
4.5 Linked Stacks and Queues(Cont’) void Stack :: Add(const int y){ top = new stackNode(y, top); } Program 4.16 : Adding to a linked stack int* Stack :: Delete(int& retvalue) // delete top node from stack and return a pointer to its data { if (top==0){StackEmpty(); return 0;}// return null pointer constant StackNode *delnode = top; retvalue=top->data; // get data field of top node top=top->link; // remove top node delete delnode; // free the node return &retvalue; // return pointer to data } Program 4.17 : Deleting from a linked stack
4.5 Linked Stacks and Queues(Cont’) void Queue :: Add(const int y) { if (front==0) front = rear = new QueueNode(y, 0); // empty queue else rear = rear->link = new QueueNode(y, 0); // attach node and update rear } Program 4.18 : Adding to a linked queue int* Queue :: Delete(int& retvalue) // delete top node in queue and return a pointer to its data { if (top==0){QueueEmpty(); return 0;} QueueNode *x = front; retvalue=front->data; // get data front=x->link; // delete front node delete x; // free the node return &retvalue; // return pointer to data } Program 4.19 : Deleting from a linked queue