500 likes | 689 Views
Chapter 3: Lists, Stacks and Queues. Concept of Abstract Data Type (ADTS) How to efficiently perform operations on list Stack ADT and its applications Queue ADT and its applications. 3.1 Abstract Data Type. Modular program Advantages: (1) debugging (2) team work (3) easy to modify.
E N D
Chapter 3: Lists, Stacks and Queues • Concept of Abstract Data Type (ADTS) • How to efficiently perform operations on list • Stack ADT and its applications • Queue ADT and its applications
3.1 Abstract Data Type • Modular program • Advantages: (1) debugging (2) team work (3) easy to modify
3.1 Abstract Data Type • Abstract data type a set of operations mathematical abstractions just as integer, boolean • Basic idea write once, use many Any changes are transparent to the other modules
3.2 List ADT • Review on linked list • Common errors memory allocation segmentation violation check for NULL pointer free memory
3.2 List ADT • Doubly linked list struct node { int Number; struct node *left; struct node *right; }
3.2.1 List ADT: Example1 • Single-variable Polynomials typedef struct { int CoeffArray[MaxDegree+1]; int HighPower } *polynomial
3.2.1 List ADT: Example 1 • Initialize a polynomial void ZeroPolynomial(Polynomial Poly) { int j; for (j = 0; j < MaxDegree; j++) poly->CoeffArray[j] = 0; Poly->HighPower = 0; }
3.2.1 List ADT: Example 1 • Add two polynomials void AddPolynomial(const Polynomial Poly1, const Polynomial Poly2, Polynomial PolySum) { int j; ZeroPolynomial(PolySum); PolySum->HighPower = Max(Poly1-> HighPower, Poly2 -> HighPower); for (j=PolySum->HighPower; j>=0; j--) PolySum->CoeffArray[j] = Poly1-> CoeffArray [j] + Poly2-> CoeffArray[j]; }
3.2.1 List ADT: Example 1 • Multiply two polynomials void MultPolynomial(const Polynomial Poly1, const Polynomial Poly2, Polynomial PolyProd) { int j,k; ZeroPolynomial(PolyProd); PolySum->HighPower = Poly1-> HighPower+ Poly2 -> HighPower; for (j=0; j=Poly1->HighPower; j++) for (k=0; k=Poly2->HighPower; k++) PolyProd->CoeffArray[j+k] += Poly1-> CoeffArray [j]* Poly2-> CoeffArray[k]; }
3.2.1 List ADT: Example 1 • Multiply two polynomials: limitation • Consider the following situation P1(X) = 10 X1000 + 5X14 + 1 P2(X) = 3X1990 - 2X1492 +11X +5 • Most of the time is spent multiplying zeros
3.2.1 List ADT: Example 1 • Multiply two polynomials: better structure struct node { int Coefficient; int Exponent; struct node *Next; }
3.2.1 List ADT: Example 1 • Linked list representation of the previous structure
3.2.2 List ADT: Example 2 • Multilists • A university with 40,000 students and 2,500 subjects needs to generate 2 reports 1. Lists of registration for each class 2. Classes that each student registered. Implementation: construct 2D array (40Kx2K5) = 100M entries if each student takes 3 subjects => only 120K entries (~0.1% of 100M) => waste of resources.
3.2.2 List ADT: Example 2 Multilists
3.3 Stack ADT • Stack model
3.3 Stack ADT • LIFO structure • Access from the top • Basic Operations • empty (s) • pop (s) • push (s, i) • top (s)
3.3.1Implementation of stack using Linked List struct Node; typedef struct Node *PtrToNode; typedef PtrToNode Stack; struct Node { ElementType Element; PtrToNode Next; }
3.3.1Implementation of stack using Linked List int IsEmpty(Stack S); Stack CreatStack(void); void DisposeStack(Stack S); void MakeEmpty(Stack S); void Push(ElementType X, Stack S); void Pop(Stack S); ElementType Top(Stack S);
3.3.1Implementation of stack using Linked List • Test for an empty stack int Isempty(Stack S) { return (SNext == NULL) }
3.3.1Implementation of stack using Linked List void MakeEmpty(Stack S) { if (S==NULL) printf(“Error message!”); else while (!IsEmpty(S)) pop(S) } • Create an empty stack stack CreatStack(void) { Stack S; S=malloc(sizeof(struct Node)); if (S==NULL) FatalError(“Out of space!!!”); MakeEmpty(S) return(S); }
3.3.1Implementation of stack using Linked List • Push onto a stack void Push(ElementType X, Stack S) { PtrtoNode TmpCell; TmpCell = malloc(sizeof(struct Node)); if (TmpCell == NULL) fatalError(“message”); else { TmpCell Element = X; TmpCell Next = S Next; S Next = TmpCell; } }
3.3.1Implementation of stack using Linked List • Return top element in a stack ElementType Top(Stack S) { if (!IsEmpty(S)) return (S Next Element); Error(“Empty stack”); return 0; }
3.3.1Implementation of stack using Linked List • Pop from a stack void Pop(Stack S) { PtrToNode FirstCell; if (ISEmpty(S); Error (“Empty stack”); else { FirstCell = S Next; S Next =S Next Next; free(FirstCell);} }
3.3.2 Implementation of stack using Array Struct StackRecord { int Capacity; int TopOfStack; ElementType *Array; } #define STACKSIZE 100 Struct StackRecord { int top; ElementType Array[STACKSIZE]; }
3.3.2 Implementation of stack using Array • Test for empty stack empty (stack *ps) { return (ps top == -1) }
3.3.2 Implementation using Array • Pop top element from stack int pop (stack *ps) { int x if (empty (ps)) printf (“%s\n”, “stack underflow!”); else { x = ps array [ps top]; (ps top)--; return (x); } }
3.3.2 Implementation using Array · Push an element onto the stack push (stack *ps, int x) { if (ps top == STACKSIZE – 1) printf (“%s\n”, “stack overflow!”); else { (ps top)++; ps items [ps top] = x; } }
3.3.3 Variable types of stack elements struct stackelement { int etype; /* element type */ union { int ival; float fval; char *pval; } element; /* end union */ } #define STACKSIZE 100 #define INTGR 1 #define FLT 2 #define STRING 3
3.3.3 Variable Types of Stack Elements • To access the top element struct stack s; struct stackelement se; se = s.items [s.top]; switch (se.etype) { case INTGR: printf (“%d\n”, se.ival); break; case FLT: printf (“%d\n”, se.fval); break; case STRING: printf (“%s\n”, se.pval); }
3.3.4 Applications • Balancing Symbols • Make an empty stack. Read characters until end of file. • If the character is an opening symbol, push it onto stack. • If it is a closing symbol, then if the stack is empty, report an error. Otherwise, pop the stack. • If the symbol popped is not the corresponding opening symbol, then report an error. • At the end of file, if the stack is not empty, report an error.
3.3.4 Applications • Postfix Expressions • 4.99+5.99+6.99*1.06 = 19.05 or 18.39 • postfix notation of (4.99*1.06 + 5.99 + 6.99*1.06) is 4.99 1.06 * 5.99 + 6.99 1.06 * + • Why do we need postfix notation?
3.3.4 Application: Postfix • How does postfix work? • e.g. 6 5 2 3 + 8 * + 3 + *
Converting infix expressions into postfix Infix A * B + C * D Postfix A B * C D * + 3.3.4 Applications
Stack -> Input Postfix String A A * * A * B A B + + A B * + C A B * C + * * A B * C + * D A B * C D pop stack A B * C D * + 3.3.4 Application: infix postfix
opstk = the empty stack; while (not end of input) { symb = next input character; if (symb is an operand) add symb in the postfix string; else { while (!empty (opstk) && prcd (stack (opstk), symb)) { topsymb = pop (opstk); add topsymb to postfix string; } push (opstk, symb); } } 3.3.4 Application: infix postfix
/* output any remaining operators */ while (!empty (opstk)) { topsymb = pop (opstk); add topsymb to the postfix string; } 3.3.4 Application: infix postfix
With parentheses Stack -> Input Postfix String ( ( ( A A ( + + A ( + B A B ) A B + * * A B + * C A B + C pop stack A B + C * 3.3.4 Application: infix postfix
Please refer to infix2postfix.doc for implementation. 3.3.4 Application: infix postfix
·Ordered collections of data items Delete item at front of the queue Insert item at rear of the queue A FIFO structure A B C D E front rear 3.4 Queue ADT
Basic operations (1) insert (q, x) (2) remove (q, x) (3) empty (q) 3.4 Queue ADT
Array implementation #define MAXQUEUE 100 struct queue { int items [MAXQUEUE]; int front, rear, length; } q; 3.4 Queue ADT
void insert (q, x) { q.length++; q.rear++; q.items [q.rear] = x; } 3.4 Queue ADT
void remove (q, x) { x = q.items [q.front]; q.front++; q.length--; } 3.4 Queue ADT
Problem: May run out of rooms (1) Keep front always at 0 by shifting the contents up the queue, but the computer solution is inefficient (2) Use a circular queue (wrap around & use a length variable to keep track of the queue length) 3.4 Queue ADT
insert (queue *pq, int x) { if ((pq length) == MAXQUEUE) /* check for overflow */ printf (“Queue overflow”); else { (pq length)++; /* make room for a new element */ if ((pq rear) == MAXQUEUE - 1) pq rear = 0; else (pq rear)++; pq items [pq rear] = x; /* check if queue is originally empty */ if ((pq length) == 1) pq front = pq rear; } } 3.4 Queue ADT
void empty (queue *pq) { if ((pq length) == 0) return (TRUE); else return (FALSE); } 3.4 Queue ADT
void remove (queue *pq) { if (empty (pq)) printf (“Queue underflow”); else if (pq front == MAXQUEUE - 1) { pq front = 0; return (pq items [MAXQUEUE - 1]); } else { (pq front)++; return (pq items [(pq front) - 1]); } } 3.4 Queue ADT
Print jobs Computer networks OS Real-life waiting lines 3.4 Applications of Queues