Presentation is loading. Please wait.

Presentation is loading. Please wait.

CH4. LINKED LISTS.

Similar presentations


Presentation on theme: "CH4. LINKED LISTS."— Presentation transcript:

1 CH4. LINKED LISTS

2 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 11/11/2018

3 4.1 Singly Linked Lists(Cont’)
List of 3-letter words : (BAT, CAT, EAT, ..., VAT, WAT) data link 1 HAT 15 2 3 CAT 4 EAT 9 5 6 7 WAT 8 BAT FAT 10 11 VAT . data[8] = BAT first = 8 link[8] = 3 data[3] = CAT Figure 4.1: Nonsequential list representation 11/11/2018

4 4.1 Singly Linked Lists(Cont’)
first BAT CAT EAT WAT Figure 4.2 : Usual way to draw a linked list 11/11/2018

5 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 11/11/2018

6 4.1 Singly Linked Lists(Cont’)
Figure 4.3 : Inserting a node 11/11/2018

7 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 Figure 4.4 : Delete GAT from list Note : must know the previous element 11/11/2018

8 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; }; 11/11/2018

9 4.2 Representing Lists in C++(Cont’)
data 22 data1 5.5 data2 link ‘c’ data3 3.14 linka linkb nodea nodeb Figure 4.5 : Illustration of the node structures nodea and nodeb 11/11/2018

10 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 11/11/2018

11 4.2 Representing Lists in C++(Cont’)
Figure 4.6 : Referencing the data members of a node 11/11/2018

12 4.2 Representing Lists in C++(Cont’)
ThreeLetter List ThreeLetter Node first CAT EAT WAT Figure 4.7 : Conceptual relationship between ThreeLetterList and ThreeLetterNode 11/11/2018

13 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 Figure 4.8 : Actual relationship between ThreeLetterList and ThreeLetterNode 11/11/2018

14 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 11/11/2018

15 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 11/11/2018

16 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 11/11/2018

17 4.2 Representing Lists in C++(Cont’)
Using composite classes, the node class can be used by two data structures 11/11/2018

18 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 11/11/2018

19 4.2 Representing Lists in C++(Cont’)
x a a b x y b y b b (a) (b) x=y (c) *x=*y Figure 4.9 : Effect of pointer assignments 11/11/2018

20 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; 11/11/2018

21 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 11/11/2018

22 4.2 Representing Lists in C++(Cont’)
first 10 20 Figure 4.10 : A two-node list 11/11/2018

23 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::Insert } //insert after x t->link = x->link; x->link = t; } Program 4.4 : Inserting a node 11/11/2018

24 4.2 Representing Lists in C++(Cont’)
first first x 50 t t 50 (a) (b) Figure 4.11 : Inserting into an empty and nonempty list 11/11/2018

25 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 11/11/2018

26 4.2 Representing Lists in C++(Cont’)
Figure 4.12 : Possible configuration for a singly linked list traversed in both directions 11/11/2018

27 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; 11/11/2018

28 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 11/11/2018

29 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; 11/11/2018

30 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 11/11/2018

31 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 11/11/2018

32 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 11/11/2018

33 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 11/11/2018

34 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; 11/11/2018

35 4.3 A Reusable Linked List Class(Cont’)
template <class Type> // return a pointer to the first element of list Type* ListIterator<Type>::First(){ if(list.first) return &list.first->data; else return 0; } template <class Type> // return a pointer to the next element of list Type* ListIterator<Type>::Next(){ if(current){ current = current->link; if (current) return &current->data; } else return 0; } Program 4.9 : List iterator functions 11/11/2018

36 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 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 11/11/2018

37 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 11/11/2018

38 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> 11/11/2018

39 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 11/11/2018

40 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 11/11/2018

41 4.3 A Reusable Linked List Class(Cont’)
1 st iteration q p 2 nd iteration r q p 11/11/2018

42 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 11/11/2018

43 Figure 4.13 : A circular list
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 EAT WAT Figure 4.13 : A circular list 11/11/2018

44 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 11/11/2018

45 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 11/11/2018

46 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 11/11/2018

47 4.5 Linked Stacks and Queues
Figure 4.17 : Linked stack and queue 11/11/2018

48 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&); StackNode *top; void StackEmpty(); Program 4.15 : Stack class definition 11/11/2018

49 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 11/11/2018

50 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 11/11/2018

51 4.6 Polynomials 4.6.1 Polynomial Representation Polynomial class
a polynomial is represented by a list Polynomial IS-IMPLEMENTED-BY List Definition a data object of Type A IS-IMPLEMENTED-BY a data object of Type B if the Type B object is central to the implementation of the Type A object Implementation linked list object poly is data member of Polynomial list template Type instatiation struct term 11/11/2018

52 4.6 Polynomials(Cont’) : polynode coef exp link term data : ListNode
11/11/2018

53 4.6 Polynomials(Cont’) Program 4.20 : Polynomial class definition
struct Term // all members of Term are public by default { int coef; // coefficient int exp; // exponent void Init(int c, int e) coef = c; exp = e; ; }; class Polynomial { friend Polynomial operator + (const Polynomial&, const Polynomial&); private: List<Term> poly; }; Program 4.20 : Polynomial class definition 11/11/2018

54 4.6 Polynomials(Cont’) a.first 3 14 2 8 1 (a) b.first 8 14 -3 10 10 6
(a) b.first 8 14 -3 10 10 6 (b) Figure 4.18 : Polynomial representation of 3x14+2x8 + 1and 8x14-3x x6 11/11/2018

55 4.6 Polynomials(Cont’) 4.6.2 Adding Polynomials
Add polynomials a and b use list iterators Aiter and Biter to examine their terms two variables p and q are used to move along the terms of a and b if p→exp == q→exp coefficients are added a new term is created for the result polynomial c if the sum is not zero if p→exp < q→exp copy of the term in b is attached to c q is advanced if p→exp > q→exp similar action is taken on a 11/11/2018

56 4.6 Polynomials(Cont’) a 3 14 2 8 1 q p b 8 14 -3 10 10 6 c 11 14
q p b 8 14 -3 10 10 6 c 11 14 (i) p  exp == q  exp a 3 14 2 8 1 p q b 8 14 -3 10 10 6 c 11 14 -3 10 (ii) p  exp < q  exp 11/11/2018

57 Figure 4.19 : Generating the first three terms of c=a+b
4.6 Polynomials(Cont’) a 3 14 2 8 1 p q b 8 14 -3 10 10 6 c 11 14 -3 10 10 8 (iii) p  exp > q  exp Figure 4.19 : Generating the first three terms of c=a+b 11/11/2018

58 4.6 Polynomials(Cont’) Polynomial operator+(const Polynomial& a, const Polynomial& b){ // Polynomials a and b are added and the sum returned Term *p, *q, temp; ListIterator<Term> Aiter(a.poly); ListIterator<Term> Biter(b.poly); Polynomial c; p = Aiter.First(); q = Biter.First(); // get first node in a and b while (Aiter.NotNull() && Biter.NotNull()){ // current node is not null switch (compare(p->exp, q->exp)){ case '=': int x = p->coef + q->coef; temp.Init(x,q->exp); if (x) c.poly.Attach(temp); p = Aiter.Next(); q = Biter.Next(); // advance to next term break; case '<': temp.Init(q->coef,q->exp); c.poly.Attach(temp); q = Biter.Next(); // next term of b break; 11/11/2018

59 4.6 Polynomials(Cont’) Program 4.21 : Adding two polynomials
case '>': temp.Init(p->coef,p->exp); c.poly.Attach(temp); p = Aiter.Next(); // next term of a } } while (Aiter.NotNull()){ // copy rest of a temp.Init(p->coef,p->exp); c.poly.Attach(temp); p = Aiter.Next(); } while (Biter.NotNull()){ // copy rest of b temp.Init(q->coef,q->exp); c.poly.Attach(temp); q = Biter.Next(); } return c; } Program 4.21 : Adding two polynomials 11/11/2018

60 4.6 Polynomials(Cont’) ListNode Type data; ListNode *Link
List ListNode<Type> *first; ListIterator List<Type> &List; ListNode<Type> *current ListIterator(List<Type> &l) Term int coef; int exp; Polynomial List<Term> Poly; Operator+(Polynomial &a, Polynomal &b) Term *p, *q, temp; ListIterator<Term> Aiter(a.Poly); ListIterator<Term> Biter(b.Poly); Polynomial c; 11/11/2018

61 4.6 Polynomials(Cont’) Analysis of operator+( )
operations contributing to the computing time : coefficient additions exponent comparisons additions/deletions to available space creation for new nodes for c assume a and b have m and n terms 0 coefficients additions minm, n exponent comparisons < m+n the computing time is O(m+n) algorithm operator+( ) is optimal within a constant factor 11/11/2018

62 4.6 Polynomials(Cont’) 4.6.3 Erasing Polynomials
Compute and print d(x)=a(x)*b(x)+c(x) Destructor ListNode<term> objects are not physically contained in List<term> objects the objects do not get automatically freed up destructor deletes all objects that are conceptually part of a class but not physically part of it void func(){ Polynomial a,b,c,d,t; cin >> a; // read and create polynomials cin >> b; cin >> c; t = a * b; d = t + c; cout << d; } 11/11/2018

63 List<Term> poly
4.6 Polynomials(Cont’) Polynomial List<Term> poly ListNode<Term> first (a) ListNode<Term> (b) Figure 4.20 : (a) and (b), respectively, show a polynomial object before and after it goes out of scope 11/11/2018

64 4.6 Polynomials(Cont’) Program 4.22 : Erasing a polynomial
template <class Type> List<Type>::~List() // Free all nodes in the chain { ListNode<Type>* next; for (; first; first = next){ next = first->link; delete first; } } Program 4.22 : Erasing a polynomial 11/11/2018

65 Figure 4.21 : Circular list representation of 3x14 + 2x8 + 1
4.6 Polynomials(Cont’) Figure 4.21 : Circular list representation of 3x14 + 2x8 + 1 11/11/2018

66 Program 4.23 : Getting a node
4.6 Polynomials(Cont’) template<class Type> ListNode<Type>* CircList :: GetNode() // Provide a node for use. { ListNode<Type>* x; if (!av) x = new ListNode<Type>; else { x = av; av = av->link;} return x; } Program 4.23 : Getting a node 11/11/2018

67 4.6 Polynomials(Cont’) Program 4.24 : Returning a node
template<class Type> void CircList<Type> :: RetNode(ListNode<Type>* x) // Free the node pointed to by x. { x->link = av; av = x; } Program 4.24 : Returning a node 11/11/2018

68 Program 4.25 : Erasing a circular list
4.6 Polynomials(Cont’) template<class KeyType> void CircList<Type> :: ~CircList() // Erase the circular list pointed by first. { if (first){ ListNode* second = first->link; // second node first->link = av; // first node linked to av av = second; // second node of list becomes front of av list first = 0; } Program 4.25 : Erasing a circular list 11/11/2018

69 4.6 Polynomials(Cont’) Figure 4.22 : Dashes indicate changes involved in erasing a circular list 11/11/2018

70 Figure 4.23 : Example polynomials
4.6 Polynomials(Cont’) Figure 4.23 : Example polynomials 11/11/2018

71 4.6 Polynomials(Cont’) Polynomial operator+ (const Polynomial& a, const Polynomial& b) { Term *p, *q, temp; CircListIterator<Temp> Aiter(a.poly); CircListIterator<Term> Biter(b.poly); Polynomial c; // assume the constructor creates a head node with exp = -1 p = Aiter.first(); q = Biter.First(); while(1) switch (compare(p->exp, q->exp)) { case ‘=’ : if (p->exp == -1) return c; else { int sum = p->coef + q->coef; c.poly.Attach(temp); } p = Aiter.Next(); q = Biter.Next(); break; 11/11/2018

72 Program 4.26 : Adding circularly represented polynomials
4.6 Polynomials(Cont’) case ‘<’ : temp.Init(q->coef, q->exp); c.poly.Attach(temp); q = Biter.Next(); break; case ‘>’ : temp.Init(p->coef, p->exp); p = Alter.Next(); } // end of switch and while } Program 4.26 : Adding circularly represented polynomials 11/11/2018

73 4.7 Equivalence Classes void equivalence() { initialize; while more pairs read the next pair (I, j); process this pair; } initialize for output; for (each object not yet output) output the equivalence class that contains this object; } // end of equivalence Program 4.27 : First pass at equivalence algorithm 11/11/2018

74 4.7 Equivalence Classes(Cont’)
void equivalence() { read n; // read in number of objects initialize seq to 0 and out to FALSE; while more pairs // input pairs read the next pair (I, j); put j on the seq[i] list; put I on the seq[j] list; } for (i=0; i<n; i++) if (out[i] == FALSE) { out[i] = TRUE; output the equivalence class that contains this object i; } // end of equivalence Program 4.28 : A more detailed version of equivalence algorithm 11/11/2018

75 4.7 Equivalence Classes(Cont’)
Figure 4.24 : Lists after pairs have been input 11/11/2018

76 4.7 Equivalence Classes(Cont’)
enum Boolean {FALSE, TRUE}; class ListNode { friend void equivalence(); private: int data; ListNode *link; ListNode(int); }; typedef ListNode*ListNodePtr; // so we can create an array of pointers using new ListNode :: ListNode(int d) { data = d; link = 0; } 11/11/2018

77 4.7 Equivalence Classes(Cont’)
void equivalence() // Input the equivalence pairs and output the equivalence classes { ifstream inFile(“equiv.in”, ios::in); // “equiv.in” is the input file if (!inFile) { cerr << “Cannot open input file” << endl; return; } int i, j, n; inFile >> n; // read number of objects // initialize seq and out ListNodePtr * seq = new ListNodePtr[n]; Boolean *out = new boolean[n]; for(i=0; i<n; i++){ seq[i] = 0; out[i] = FALSE; 11/11/2018

78 4.7 Equivalence Classes(Cont’)
// Phase 1: input equivalence pairs inFile >> i>> j; while (inFile.good()) { // check end of file ListNode *x = new ListNode(j); x->link = seq[i]; seq[i] = x; // add j to seq[i] ListNode *x = new ListNode(j); x->link = seq[j]; seq[j] = x; // add j to seq[j] inFile >> i >>j; } // Phase 2:output equivalence classes for(i=0; i<n; i++) if(out[i] == FALSE) { // needs to be output cout << endl << “A new class: “ << i; out[i] = TRUE; ListNode *x = seq[i]; ListNode *top = 0; // init stack while(1) { // find rest of class while(x) { // process the list j = x -> data; 11/11/2018

79 4.7 Equivalence Classes(Cont’)
if(out[j] == FALSE) { cout << “,” << j; out[j] = TRUE; ListNode *y = x -> link; x -> link = top; top = x; x = y; } else x = x -> link; } // end of while(x) if(!top) break; else { x = seq[top -> data]; top = top -> link; // unstack } // end of while(1) } // end of if(out[i] == FALSE) 11/11/2018

80 4.7 Equivalence Classes(Cont’)
for(i=0; i<n; i++) while(seq[i]) { ListNode *delnode = seq[i]; seq[i] = delnode -> link; delete delnode; } delete [] seq; delete [] out; } // end of equivalence Program 4.29 : Algorithm to find equivalence classes 11/11/2018

81 Figure 4.25 : Node structure for sparse matrices
11/11/2018

82 4.8 Sparse Matrices(Cont’)
Figure 4.26 : 6 × 7 sparse matrix A 11/11/2018

83 4.8 Sparse Matrices(Cont’)
Figure 4.27 : Linked representation of the sparse matrix A of Figure (the head data member of a node is not shown) 11/11/2018

84 4.8 Sparse Matrices(Cont’)
Enum Boolean {FALSE, TRUE}; Struct Triple {int value, row, col;}; Class Matrix; // forward declaration Class MatrixNode { friend class Matrix; friend istream& operator >> (istream&, Matrix&); // for reading in a matrix private: MatrixNode *down, *right; Boolean head; union { // anonymous union MatrixNode *next; Triple triple; }; MatrixNode(Boolean, Triple *); // constructor 11/11/2018

85 4.8 Sparse Matrices(Cont’)
MatrixNode::MatrixNode(Boolean b, Triple *t) // constructor { head = b; if(b) { right = next = down = this;} //row/column head node else triple = *t; // head node for list of headnodes OR element node } typedef MatrixNode *Matrix NodePtr; // to allow subsequent creation of array of pointers class Matrix friend istream& operator >> (istream&, Matrix&); public: ~Matrix(); // destructor private: MatrixNode *headnode; }; Program 4.30 : Class definition for sparse matrices 11/11/2018

86 4.8 Sparse Matrices(Cont’)
istream& operator >> (istream& is, Matrix& matrix) // Read in a matrix and wet up its linked representation. // An auxiliary array head is used. { Triple s; int p; is >> s.row >> s.col >> s.value; // matrix dimensions if(s.row>s.col) p = s.row; else p=s.col; // set up headnode for list of head nodes. matrix.headnode = new MatrixNode(FALSE, &s); if(p == 0) {matrix.headnode -> right = matrix.headnode; return is; } // at least one row or column MatrixNodePtr *head = new MatrixNodePtr[p]; //initialize head nodes for(int i=0; i<p; i++) head[i] = new MatrixNode(TRUE,0); int CurrentRow = 0; MatrixNode *last = head[0]; // last node in current row 11/11/2018

87 4.8 Sparse Matrices(Cont’)
for(i=0; i<s.value; i++) // input triples { Triple t; is >> t.row >> t.col >> t.value; if(t.row > CurrentRow) { //close current row last -> right = head[CurrentRow]; CurrentRow = t.row; last = head[CurrentRow]; } // end of if last = last - >right = new MatrixNode(FALSE, &t); // link new node into row list head[t.col] -> next = head[t.col] -> next - >dows = last; //link into column list } // end of for last -> right = head[CurrentRow]; // close last row for(i=0; i<s.col; i++) head[i] -> enxt -> down = head[i]; // close all column lists // link the head nodes together 11/11/2018

88 4.8 Sparse Matrices(Cont’)
for(i=0; i<p-1; i++) head[i] -> next = head[i+1]; head[p-1] -> next = matrix.headnode; matrix.headnode -> right = head[0]; delete[] head; return is; } Program 4.31 : Reading in a sparse matrix 11/11/2018

89 4.8 Sparse Matrices(Cont’)
Matrix::~Matrix() // Return all nodes to the av list. This list is a chain linked via the right // field. av is a global variable of type MatrixNode * and points to its first node. { if(!headnode) return; // no nodes to dispose MatrixNode *x = headnode -> right, *y; headnode -> right = av; av = headnode; // return headnode while(x != headnode) { // erase by rows y = x -> right; x -> right = av; av = y; x = x -> next; // next row } headnode = 0; Program 4.32 : Erasing a sparse matrix 11/11/2018

90 4.8 Sparse Matrices(Cont’)
Figure 4.28 : Representation of matrix A of Figure using the scheme of Exercise 6 11/11/2018

91 4.9 Doubly Linked Lists Problems with singly linked lists Node
can move only in the direction of the links deletion requires knowing the preceding node Node at least three fields : data, llink(left link), rlink(right link) 11/11/2018

92 4.9 Doubly Linked Lists(Cont’)
HeadNode LeftLink data RightLink Figure 4.29 : Doubly linked circular list with head node 11/11/2018

93 4.9 Doubly Linked Lists(Cont’)
Head node convenient for algorithms data field usually contains no information Essential virtue one can go back and forth with equal ease p==p→llink→rlink==p→rlink→llink first Figure 4.30 : Empty doubly linked circular list with head node 11/11/2018

94 4.9 Doubly Linked Lists(Cont’)
class DblList; class DblListNode{ friend class DblList; private: int data; DblListNode *llink, *rlink; }; class DblList{ public: // List manipulation operations private: DblListNode *first; // points to head node }; Program 4.33 : Class definition of a doubly linked list 11/11/2018

95 4.9 Doubly Linked Lists(Cont’)
void DblList::Delete(DblListNode *x) { if ( x == first ){ cerr << "Deletion of headnode not permitted?<< endl; }else{ x->llink->rlink = x->rlink; x->rlink->llink = x->llink; delete x; } } Program 4.34 : Deletion from a doubly linked circular list 11/11/2018

96 4.9 Doubly Linked Lists(Cont’)
x  llink x x  rlink Figure 4.31 : Deletion from a doubly linked circular list 11/11/2018

97 4.9 Doubly Linked Lists(Cont’)
void DblList::Insert(DblListNode *p, DblListNode *x) // insert node p to the right of node x { p->llink = x; p->rlink = x->rlink; x->rlink->llink = p; x->rlink = p; } Program 4.35 : Insertion into a doubly linked circular list 11/11/2018

98 4.9 Doubly Linked Lists(Cont’)
p x 11/11/2018

99 4.10 Generalized Lists Figure 4.32 : Representation of 3x2y 11/11/2018

100 4.10 Generalized Lists(Cont’)
Figure 4.33 : Representation of P (x, y, z) 11/11/2018

101 4.10 Generalized Lists(Cont’)
Figure 4.34 : Representation of lists (1) to (4) 11/11/2018

102 4.10 Generalized Lists(Cont’)
// Driver void GenList::Copy(const GenList& l) { first = Copy(l.first); } // Workhorse GenListNode* GenList::Copy(GenListNode* p) { // Copy the nonrecursive list with no shared sublists pointed at by p GenListNode *q = 0; if(p) { q = new GenListNode; q -> tag = p -> tag; if (!p -> tag) q -> data = p -> data; else q -> dlink = Copy(p -> dlink); q -> link = Copy(p -> link); return q; Program 4.36 : Copying a list 11/11/2018

103 4.10 Generalized Lists(Cont’)
Figure 4.35 : Linked representation for A 11/11/2018

104 4.10 Generalized Lists(Cont’)
Figure 4.36 : Values of parameters in execution of GenList :: Copy (A) 11/11/2018

105 4.10 Generalized Lists(Cont’)
// Driver – assumed to be a friend of GenList int operator == (const GenList& l, const GenList& m) { // l and m are non-recursive lists. // The function returns 1 if the two lists are identical and 0, otherwise. return equal(l.first, m.first); } // Workhorse – assumed to be a friend of GenListNode int equal(GenListNode* s, GenListNode *t) { int x; if ((!s) && (!t)) return 1; if (s && t && (s -> tag == t -> tag)){ if (!s -> tag) if (s -> data == t -> data) x =1; else x = 0; else x = equal(s -> dlink, t -> dlink); if (x) return equal(s -> link, t -> link); return 0; Program 4.37 : Determining if two lists are identical 11/11/2018

106 4.10 Generalized Lists(Cont’)
// Driver int GenList::depth() P // Compute the depth of a non-recursive list return depth(first); } // Workhorse int GenList::depth(GenListNode *s) { if (!s) return 0; GenListNode *p = s; int m = 0; while(p) { if (p -> tag) { int n = depth(p -> dlink); if (m < n) m = n; p = p -> link; return m+1; Program 4.38 : Computing the depth of a list 11/11/2018

107 4.10 Generalized Lists(Cont’)
Figure 4.37 : Structure with head nodes for lists (1) to (4) 11/11/2018

108 4.10 Generalized Lists(Cont’)
Figure 4.38 : t = (3x4 + 5x3 + 7x)y3, u = (3x4 + 5x3 + 7x)y6 + (6x)y 11/11/2018

109 4.10 Generalized Lists(Cont’)
// Driver GenList::~GenList() { // Each head node has a reference count. We assume first ≠ 0. Delete(first); first = 0; } // Workhorse void GenList::Delete(GenListNode* x) { x -> ref--; //decrement reference count of head node. if (!x -> ref) GenListNode *y = x; // y traverses top-level of x. while (y -> link) { y = y -> link; if ( y -> tag==1) Delete (y -> dlink);} y -> link = av; // attach top-level nodes to av list av = x; Program 4.39 : Erasing a list recursively 11/11/2018

110 4.10 Generalized Lists(Cont’)
Figure 4.39 : Indirect recursion of lists A and B pointed to by program variables r and s 11/11/2018

111 4.11 Virtual Functions and Dynamic Binding in C++
Dynamic types consequence of public inheritance a pointer (reference) to a derived class type is implicitly converted to a pointer (reference) to its base class example Rectangle IS-A Polygon a pointer to a Polygon type can be assigned the address of a Rectangle object Rectangle r ; Polygon *s = &r; (derived) (base) (derived) supported by C++ virtual functions dynamically bound : the operation corresponding to the dynamic type of the object that invoked it, is used the dynamic type of s is Rectangle 11/11/2018

112 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
class Polygon { public: int GetId(); // non-virtual member function virtual Boolean Concave(); // virtual member function virtual int Perimeter() = 0; // pure virtual member function protected: int id; }; 11/11/2018

113 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
class Rectangle : public Polygon // Rectangle publicly inherits from Polygon { public: Boolean Concave(); // redefined in Rectangle int Perimeter; // defined in Rectangle // GetId() and id are inherited from Polygon // They, respectively, become public and protected members of Rectangle private: // additional data members required to specialize Rectangle int x1, y1, h, w; }; 11/11/2018

114 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
// GetId() must never be redefined in a derived class int Polygon::GetId() { return id;} // Default implementation of Concave() in Polygon. A Polygon is // concave if it is possible to construct a line joining two points // in the polygon that does entirely lie within the polygon. Boolean Polygon::Concave(){ return TRUE;} // Rectangle must define Perimeter() because it is a pure virtual // function. int Rectangle::Perimeter{return 2*(h + w);} // The default implementation of Concave() does not apply to // rectangles. So, it has to be redefined. Boolean Rectangle::Concave{ return FALSE; } Program 4.40 : Public inheritance 11/11/2018

115 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
Three types of member functions (a) Virtual member function its prototype is preceded by the keyword virtual if a virtual function, whose implementation is redefined in a derived class, is invoked by a base class, then the implementation corresponding to the current dynamic type of that base class object is used Rectangle r; . . // assume r is initialized at this point Polygon *s = &r; s->Concave(); // returns FALSE Program 4.41 : Virtual member function operation 11/11/2018

116 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
(b) Non-virtual member function not preceded by the virtual keyword in the base class use non-virtual functions in base classes only if they will not be redefined in a derived class (if redefined, there is an inconsistency) Rectangle r; . . // assume r is initialized at this point Polygon *s = &r; s->GetId(); // uses the function implemented in Polygon Rectangle *t = &r; t->GetId(); // uses the function implemented in Rectangle Program 4.42 : Reimplementing a non-virtual function 11/11/2018

117 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
(c) Pure virtual function it is not implemented by its class it is assigned value 0 to indicate that it is pure abstract class base class with pure virtual functions consequences not allowed to create instances of the abstract class Polygon p; // illegal Polygon *q; // legal Pure virtual function must be redefined in the derived class a base class must support a particular function, but the implementation requires additional information 11/11/2018

118 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
Rectangle r; // assume r is initialized at this point Polygon *s = &r; s->Perimeter(); // returns perimeter of r Program 4.43 : Pure, virtual member function operation 11/11/2018

119 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
struct Data { int id; // id = 0,1, or 2 if the node contains a char, an int, or float, respectively union { int i; char c; float f; }; class CombinedNode // use union to merge different node types into one class definition friend class List; friend clas ListIterator; private: Data data; CombinedNode *link; 11/11/2018

120 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
class List { friend class ListIterator; public: // List manipulation operations follow . private: CombinedNode *first; }; // class ListIterator is defined as in Section 4.3, except that the return types // of First and Next are Data* Program 4.44 : Using union to implement a list of mixed nodes 11/11/2018

121 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
// struct Data is assumed to be defined as in Program 4.44 class Node { friend class List; friend class ListIterator; protected: Node *link; virtual Data GetData() = 0; }; template<class Type> class DerivedNode : public Node { friend class List; friend class ListIterator; public: DerivedNode(Type item) : data(item) { link = 0; }; private: Type data; Data GetData(); 11/11/2018

122 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
Data DerivedNode<char>::GetData() { Data t; t.id = 0; t.c = data; return t; } // The implementations of GetData() for DerivedNode<int> and DerivedNode<float> // are similar to that of DerivedNode<char>::GetData(). class List { friend class ListIterator; public: // List manipulation operations follow . private: Node *first; }; 11/11/2018

123 4.11 Virtual Functions and Dynamic Binding in C++(Cont’)
class ListIterator { public: ListIterator(const List& l): list(l), current(l.first) {}; Data* First(); // minor change in homogeneous list implementation Data* Next(); // minor change in homogeneous list implementation Boolean NotNull(); // implemented as for homogeneous lists Boolean NextNotNull(); // implemented as for homogeneous lists private: const List& list; Node* current; Data temp; }; Data* ListIterator::First() { if(list.first) { temp = list.first -> GetData(); // use GetData to retrieve element return &temp; } return 0; Program 4.45 : Using public inheritance to implement a list of mixed nodes 11/11/2018


Download ppt "CH4. LINKED LISTS."

Similar presentations


Ads by Google