Data Structures Abstract Data 1 ADT Abstract data
Data Structures Abstract Data 1
ADT: Abstract data types §A set of data values and associated operations that are precisely specified independent of any particular implementation. §A kind of data abstraction where a type's internal form is hidden behind a set of access functions. Values of the type are created and inspected only by calls to the access functions. This allows the implementation of the type to be changed without requiring any changes outside the module in which it is defined. 2
ADT-Stack §A classic example of an ADT is a stack data type for which functions might be provided to create an empty stack, to push values onto a stack and to pop values from a stack. 3
Stacks, LIFO §A stack can have any abstract data type as an element, but is characterized by two fundamental operations, called push and pop. §first proposed in 1946, in the computer design of Alan M. Turing (who used the terms "bury" and "unbury") as a means of calling and returning from subroutines. §Applications: functions, simulation (planes, garages, …), parsing, … 4
Abstract Stack Also called a last-in–first-out (LIFO) behaviour § Graphically, we may view these operations as follows:
Stack ADT §Collections: § Elements of some proper type T §Operations: § void push(T t) void pop() T top() bool empty() unsigned int size() § constructor and destructor § §
Stack Model—LIFO §Empty stack S n n n S. empty() is true S. top() not defined S. size() == 0 §S. push(“mosquito”) n n n S. empty() is false S. top() == “mosquito” S. size() == 1 §S. push(“fish”) n n n S. empty() is false S. top() == “fish” S. size() == 2 food chain stack
Memory Organization Process 1 (browser) Code Process 3 (word) Static data Process 4 (excel) Stack Process 2 (dev-c++) Windows OS Heap
Stack Layout during a call §Here is stack layout when function F calls function G: Parameters(F) sp Parameters(F) Local variables(F) Return address(F) Parameters(G) sp Local variables(G) sp At point of call Return address(G) During execution of G After call
Stack Implementation Array Need to know the maximum number of elements Delete/Access/Add at the end O(1) operation. Store array length in the 0 th position. Delete/Access/Add at A[array length+1]
Stacks - Implementation §Arrays § § Provide a stack capacity to the constructor Flexibility limited but matches many real uses § Capacity limited by some constraint § § Memory in your computer Size of the plate stacker, etc §push, pop methods § Variants of Add. To. C…, Delete. From. C… §Stack: § basically a Collection with special semantics!
An Array-Based Implementation An array that implements a stack; its first location references (a) the top of the stack; (b) the bottom of the stack
Stacks - Relevance §Stacks appear in computer programs § § Key to call / return in functions & procedures Stack frame allows recursive calls Call: push stack frame Return: pop stack frame §Stack frame § § § Function arguments Return address Local variables
Stacks #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; int main() { Stack s; } 14 return 0;
Stacks #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int main() { Stack s; } 15 return 0;
Stacks #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int main() { Stack s; push(&s, 5); push(&s, 6); printf("[%d]", pop(&s)); return 0; } 16
Stacks #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int main() { Stack s; push(&s, 5); push(&s, 6); printf("[%d]", pop(&s)); return 0; } 17
Stacks #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; [6][5] Process returned 0 (0 x 0) … void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int main() { Stack s; s. top=0; push(&s, 5); push(&s, 6); printf("[%d]", pop(&s)); return 0; } 18
Stacks #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; [6][5] Process returned 0 (0 x 0) … void initialize(Stack *s) {s->top=0; } void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int main() { Stack s; initialize(&s); push(&s, 5); push(&s, 6); printf("[%d]", pop(&s)); return 0; } 19
Stacks – Error Management #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; [6][-1 ? ? ] Process returned 0 (0 x 0) … void initialize(Stack *s) {s->top=0; } void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int main() { Stack s; initialize(&s); push(&s, 5); printf("[%d]", pop(&s)); return 0; } 20
Stacks – Error Management #include <stdio. h> #include <stdlib. h> #define TYPE int #define STACKSIZE 1000 typedef struct { int top; TYPE items[STACKSIZE]; } Stack; void initialize(Stack *s) {s->top=0; } void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int main() { Stack s; initialize(&s); push(&s, 5); int i; for (i=0; i<STACKSIZE+10; i++) push(&s, i); return 0; } 21
Stacks – Error Management typedef struct { int top; TYPE items[STACKSIZE]; } Stack; void initialize(Stack *s) {s->top=0; } void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int isfull(Stack *s) {return s->top<STACKSIZE? 0: 1 ; } //if top<STACKSIZE return 0 else return 1; int main() { Stack s; initialize(&s); int i; for (i=0; i<STACKSIZE+10; i++) if (!isfull(&s)) push(&s, i); return 0; } 22
Stacks – Error Management typedef struct { int top; TYPE items[STACKSIZE]; } Stack; void initialize(Stack *s) {s->top=0; } void push(Stack *s, TYPE value) {s->items[s->top++]=value; } TYPE pop(Stack *s) {return s->items[--s->top]; } int isfull(Stack *s) {return s->top<STACKSIZE? 0: 1 ; } //if top<STACKSIZE return 0 else return 1; int isempty(Stack *s) {return s->top==0? 1: 0; } //if top==0 return 1 else return 0; int main() { Stack s; initialize(&s); int i; for (i=0; i<STACKSIZE+10; i++) if (!isfull(&s)) push(&s, i); while (!isempty(&s)) printf("[%d]", pop(&s)); return 0; } 23 [99][98]. . . [3][2][1][0]
Uses of ADT Stack §Depth first search / backtracking §Evaluating postfix expressions §Converting infix to postfix §Function calls (runtime stack) §Recursion
Examples - Decimal to binary 1100001001 Stack s; initialize(&s); int x=777; while(x) {push(&s, x%2); x/=2; } while(! isempty(&s)) printf("%d", pop(&s)); 25
Evaluating Postfix Stack s; while( not end of input ) { e = get next element of input if( e is an operand ) s. push( e ); else { op 2 = s. pop(); op 1 = s. pop(); value = result of applying operator ‘e’ to op 1 and op 2; s. push( value ); } } finalresult = s. pop();
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 op 1 op 2 value 6 stack
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 op 1 op 2 value 6 6, 2 stack
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 op 1 op 2 value 6 6, 2, 3 stack
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + op 1 op 2 2 3 value 6 6, 2, 3 5 stack 6, 5
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + - op 1 op 2 2 6 3 5 value 6 6, 2, 3 5 1 stack 6, 5 1
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 op 1 op 2 2 6 6 3 5 5 value 6 6, 2, 3 5 1 1 stack 6, 5 1 1, 3
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 op 1 op 2 2 6 6 6 3 5 5 5 value 6 6, 2, 3 5 1 1 1 stack 6, 5 1 1, 3, 8
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 op 1 op 2 2 6 6 3 5 5 value 6 6, 2, 3 5 1 1 stack 6, 5 1 1, 3, 8, 2
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / op 1 op 2 2 6 6 8 3 5 5 2 value 6 6, 2, 3 5 1 1 4 stack 6, 5 1 1, 3, 8, 2 1, 3, 4
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / + op 1 op 2 2 6 6 8 3 3 5 5 2 4 value 6 6, 2, 3 5 1 1 4 7 stack 6, 5 1 1, 3, 8, 2 1, 3, 4 1, 7
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / + * op 1 op 2 2 6 6 8 3 1 3 5 5 2 4 7 value 6 6, 2, 3 5 1 1 4 7 7 stack 6, 5 1 1, 3, 8, 2 1, 3, 4 1, 7 7
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / + * 2 op 1 op 2 2 6 6 8 3 1 1 3 5 5 2 4 7 7 value 6 6, 2, 3 5 1 1 4 7 7 7 stack 6, 5 1 1, 3, 8, 2 1, 3, 4 1, 7 7 7, 2
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / + * 2 op 1 op 2 2 6 6 8 3 1 1 7 3 5 5 2 4 7 7 2 value 6 6, 2, 3 5 1 1 4 7 7 7 49 stack 6, 5 1 1, 3, 8, 2 1, 3, 4 1, 7 7 7, 2 49
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / + * 2 3 op 1 op 2 2 6 6 8 3 1 1 7 7 3 5 5 2 4 7 7 2 2 value 6 6, 2, 3 5 1 1 4 7 7 7 49 49 stack 6, 5 1 1, 3, 8, 2 1, 3, 4 1, 7 7 7, 2 49 49, 3
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / + * 2 3 + op 1 op 2 2 6 6 8 3 1 1 7 7 49 3 5 5 2 4 7 7 2 2 3 value 6 6, 2, 3 5 1 1 4 7 7 7 49 49 52 stack 6, 5 1 1, 3, 8, 2 1, 3, 4 1, 7 7 7, 2 49 49, 3 52
Evaluating Postfix Evaluate 6 2 3 + - 3 8 2 / + * 2 3 + Input 6 2 3 + 3 8 2 / + * 2 3 + op 1 op 2 2 6 6 8 3 1 1 7 7 49 3 5 5 2 4 7 7 2 2 3 value 6 6, 2, 3 5 1 1 4 7 7 7 49 49 52 stack 6, 5 1 1, 3, 8, 2 1, 3, 4 1, 7 7 7, 2 49 49, 3 52
Examples - Evaluate Postfix /* Evaluate Postfix Notation 124*+3+ if operand push it else pop 2 and evaluate and push it again */ void error() {printf("error"); exit(-1); } int main() { Stack s; initialize(&s); char *post. Exp="1 2 4 * + 3 +"; int i; for (i=0; i<strlen(post. Exp); i++) if (post. Exp[i]==' ') continue; if (post. Exp[i]<='9' && post. Exp[i]>='0') push(&s, post. Exp[i]-'0'); else { 43 } } printf("%s=%d", post. Exp, pop(&s)); return 0;
Examples - Evaluate Postfix /* Evaluate Postfix Notation 124*+3+ if operand push it else pop 2 and evaluate and push it again */ 44 void error() {printf("error"); exit(-1); } int main() { Stack s; initialize(&s); char *post. Exp="1 2 4 * + 3 +"; int i; for (i=0; i<strlen(post. Exp); i++) if (post. Exp[i]==' ') continue; if (post. Exp[i]<='9' && post. Exp[i]>='0') push(&s, post. Exp[i]-'0'); else { int a, b; if (isempty(&s)) error(); else a=pop(&s); if (isempty(&s)) error(); else b=pop(&s); switch(post. Exp[i]) { case '+': push(&s, a+b); break; case '-': push(&s, a-b); break; case '*': push(&s, a*b); break; case '/': push(&s, a/b); break; default: error(); } // switch } printf("%s=%d", post. Exp, pop(&s)); return 0; }
Examples - Evaluate Postfix /* Evaluate Postfix Notation 124*+3+ if operand push it else pop 2 and evaluate and push it again */ 45 void error() {printf("error"); exit(-1); } int main() { Stack s; initialize(&s); char *post. Exp="1 2 4 * + 3 +"; int i; for (i=0; i<strlen(post. Exp); i++) if (post. Exp[i]==' ') continue; if (post. Exp[i]<='9' && post. Exp[i]>='0') push(&s, post. Exp[i]-'0'); else { int a, b; if (isempty(&s)) error(); else a=pop(&s); if (isempty(&s)) error(); else b=pop(&s); switch(post. Exp[i]) { case '+': push(&s, a+b); break; case '-': push(&s, a-b); break; case '*': push(&s, a*b); break; case '/': push(&s, a/b); break; default: error(); } // switch } printf("%s=%d", post. Exp, pop(&s)); return 0; }
Examples - Evaluate Postfix /* Evaluate Postfix Notation 124*+3+ if operand push it else pop 2 and evaluate and push it again */ 46 void error() {printf("error"); exit(-1); } int main() { Stack s; initialize(&s); char *post. Exp="1 2 4 * + 3 +"; int i; for (i=0; i<strlen(post. Exp); i++) if (post. Exp[i]==' ') continue; if (post. Exp[i]<='9' && post. Exp[i]>='0') push(&s, post. Exp[i]-'0'); else { int a, b; if (isempty(&s)) error(); else a=pop(&s); if (isempty(&s)) error(); else b=pop(&s); switch(post. Exp[i]) { case '+': push(&s, a+b); break; case '-': push(&s, a-b); break; case '*': push(&s, a*b); break; case '/': push(&s, a/b); break; default: error(); } // switch } printf("%s=%d", post. Exp, pop(&s)); 1 2 4 * + 3 +=12 return 0; }
Examples - Evaluate Postfix 47 int main() { Stack s; initialize(&s); char *post. Exp="1 2 4 * + 3 +"; int I; char ch, *pt=post. Exp; while (ch=*pt++) { if (ch==' ') continue; if (ch<='9' && ch>='0') push(&s, ch-'0'); else { int a, b; if (isempty(&s)) error(); else a=pop(&s); if (isempty(&s)) error(); else b=pop(&s); switch(ch) { case '+': push(&s, a+b); break; case '-': push(&s, a-b); break; case '*': push(&s, a*b); break; case '/': push(&s, a/b); break; default: error(); } // switch } } printf("%s=%d", post. Exp, pop(&s)); 124*+3 return 0; } +=12
Infix to Postfix Infix A+B 12 + 60 – 23 (A + B)*(C – D ) A B * C – D + E/F Postfix AB+ 12 60 + 23 – AB+CD–* A B C*D – E F/+
Infix to Postfix §Note that the postfix form an expression does not require parenthesis. §Consider ‘ 4+3*5’ and ‘(4+3)*5’. The parenthesis are not needed in the first but they are necessary in the second. §The postfix forms are: 4+3*5 435*+ (4+3)*5 43+5*
Examples – Infix to Postfix 1. Read an character input 2. Switch case on input: case Opening brackets (2. 1) Push into stack, Go to step (1) Number (2. 2) Print, Go to step (1) Operator (2. 3) Push into stack, Go to step (1) Closing brackets (2. 4) Pop it from the stack (2. 4. 1) If it is an operator, print it, Go to step (2. 4) (2. 4. 2) If it is an opening bracket, discard, go to step (1) end (2. 5) STOP 50
Converting Infix to Postfix §Consider the infix expressions ‘A+B*C’ and ‘ (A+B)*C’. §The postfix versions are ‘ABC*+’ and ‘AB+C*’. §The order of operands in postfix is the same as the infix. §In scanning from left to right, the operand ‘A’ can be inserted into postfix expression.
Converting Infix to Postfix §The ‘+’ cannot be inserted until its second operand has been scanned and inserted. §The ‘+’ has to be stored away until its proper position is found. §When ‘B’ is seen, it is immediately inserted into the postfix expression. §Can the ‘+’ be inserted now? In the case of ‘A+B*C’ cannot because * has precedence.
Converting Infix to Postfix §In case of ‘(A+B)*C’, the closing parenthesis indicates that ‘+’ must be performed first. §Assume the existence of a function ‘prcd(op 1, op 2)’ where op 1 and op 2 are two operators. §Prcd(op 1, op 2) returns TRUE if op 1 has precedence over op 2, FASLE otherwise.
Converting Infix to Postfix §prcd(‘*’, ’+’) is TRUE §prcd(‘+’, ’*’) is FALSE §Here is the algorithm that converts infix expression to its postfix form. §The infix expression is without parenthesis.
Converting Infix to Postfix 1. Stack s; 2. While( not end of input ) { 3. c = next input character; 4. if( c is an operand ) 5. add c to postfix string; 6. else { 7. while( !s. empty() && prcd(s. top(), c) ){ 8. op = s. pop(); 9. add op to the postfix string; 10. } 11. s. push( c ); 12. } 13. while( !s. empty() ) { 14. op = s. pop(); 15. add op to postfix string; 16. }
Converting Infix to Postfix §Example: A + B * C symb A postfix A stack
Converting Infix to Postfix §Example: A + B * C symb A + postfix A A stack +
Converting Infix to Postfix §Example: A + B * C symb A + B postfix A A AB stack + +
Converting Infix to Postfix §Example: A + B * C symb A + B * postfix A A AB AB stack + + +*
Converting Infix to Postfix §Example: A + B * C symb A + B * C postfix A A AB AB ABC stack + + +* +*
Converting Infix to Postfix §Example: A + B * C symb A + B * C postfix A A AB AB ABC * stack + + +* +* +
Converting Infix to Postfix §Example: A + B * C symb A + B * C postfix A A AB AB ABC * + stack + + +* +* +
Converting Infix to Postfix §Handling parenthesis §When an open parenthesis ‘(‘ is read, it must be pushed on the stack. §This can be done by setting prcd(op, ‘(‘ ) to be FALSE. §Also, prcd( ‘(‘, op ) == FALSE which ensures that an operator after ‘(‘ is pushed on the stack.
Converting Infix to Postfix §When a ‘)’ is read, all operators up to the first ‘(‘ must be popped and placed in the postfix string. §To do this, prcd( op, ’)’ ) == TRUE. §Both the ‘(‘ and the ‘)’ must be discarded: prcd( ‘(‘, ’)’ ) == FALSE. §Need to change line 11 of the algorithm.
Converting Infix to Postfix if( s. empty() || symb != ‘)’ ) s. push( c ); else s. pop(); // discard the ‘(‘ prcd( ‘(‘, op ) = FALSE for any operator prcd( op, ‘(’ ) = FALSE for any operator other than ‘(’ prcd( op, ‘)’ ) = TRUE for any operator other than ‘(‘ prcd( ‘)’, op ) = error for any operator.
Examples – Infix to Postfix 66 Stack s; initialize(&s); // Input: (((8 + 1) - (7 - 4)) / (11 - 9)) // Output: 8 1 + 7 4 - - 11 9 - / char * in. Str="(((8 + 1) - (7 - 4)) / (11 - 9))"; int i; char ch, ch 1, *pt=in. Str; while (ch=*pt++){ // step 1 if (ch>='0' && ch<='9') printf("%c ", ch); else switch(ch) { case '(': case '+': case '-': case '*': case '/': push(&s, ch); break; case ')': while (!isempty(&s)) { ch 1=pop(&s); if (ch 1=='(') break; printf("%c ", ch 1); } } }
Examples – Infix to Postfix infix-postfix. txt while there are more characters in the input { Read next symbol ch in the given infix expression. If ch is an operand put it on the output. If ch is an operator i. e. * , /, +, -, or ( { If stack is empty push ch onto stack; Else check the item op at the top of the stack; while (more items in the stack && priority(ch) <= priority (op) ) { pop op and append it to the output, provided it Is not an open parenthesis op = top element of stack (((8 + 1) - (7 - 4)) / (11 } push ch onto stack 81+74 } a+b/c<-->a b c / + If ch is right parenthesis ‘)’ Pop items from stack until left parenthesis a/b+c<-->a b / c + reached Pop left parenthesis and discard both left. and right parenthesis }/* now no more characters in the infix expression*/ Pop remaining items in the stack to the output. 67 9))<--> - - 11 9 - /
Recursion §Very useful technique § Definition of mathematical functions § Definition of data structures § Recursive structures are naturally processed by recursive functions! §Recursively defined functions § § § factorial Fibonacci GCD by Euclid’s algorithm Fourier Transform Games § Towers of Hanoi § Chess
Recursion - Example §Fibonacci Numbers Pseudo-code C fib( n ) = if ( n = 0 ) then 1 else if ( n = 1 ) then 1 else fib(n-1) + fib(n-2) int fib( n ) { if ( n < 2 ) return 1; else return fib(n-1) + fib(n-2); } Simple, elegant solution!
Recursion - Example !!! ! r e t as s i §CFibonacci Numbers d e int fib( n ) { m i t un r a , if ( n <ca 2 se) return 1; i c c a else on return fib(n-1) + fib(n-2); b i F e h t n i } But, However, many recursive functions, eg binary search, are simple, elegant and efficient!
Queue Abstract Data Type §A queue is a data structure that models/enforces the first-come first-serve order, or equivalently the first-in first-out (FIFO) order. §That is, the element that is inserted first into the queue will be the element that will deleted first, and the element that is inserted last is deleted last. §A waiting line is a good real-life example of a queue. (In fact, the British word for “line” is “queue”. ) 71
Queue - FIFO §Collection § Elements of some proper type T §Operations § void push(T t) void pop() T front() bool empty() unsigned int size() § Constructors and destructors § §
Deque<T> D Illustrated §content_size = 8 §D. empty() == true content 0 begin end 1 2 3 4 5 6 7
Deque<char> D Illustrated (2) §content_size = 8 §D. push_back(‘M’) content 0 M 1 begin end 2 3 4 5 6 7
Deque<char> D Illustrated (3) §content_size = 8 §D. push_back(‘e’) content 0 M begin 1 e 2 end 3 4 5 6 7
Deque<char> D Illustrated (4) §content_size = 8 §D. push_back(‘r’) content 0 M begin 1 e 2 r 3 end 4 5 6 7
Deque<char> D Illustrated (5) §content_size = 8 §D. push_back(‘r’) content 0 M begin 1 e 2 r 3 r 4 end 5 6 7
Deque<char> D Illustrated (6) §content_size = 8 §D. push_back(‘y’) content 0 M begin 1 e 2 r 3 r 4 y 5 end 6 7
Deque<char> D Illustrated (7) §content_size = 8 §D. pop_front() §O(1) content 0 1 e begin 2 r 3 r 4 y 5 end 6 7
Deque<char> D Illustrated (8) §content_size = 8 §D. pop_front() content 0 1 2 r begin 3 r 4 y 5 end 6 7
Deque<char> D Illustrated (9) §content_size = 8 §D. push_back(‘G’) content 0 1 2 r begin 3 r 4 y 5 G 6 end 7
Deque<char> D Illustrated (10) §content_size = 8 §D. push_back(‘o’) §D. size() == (7 – 2 + 8) % 8 content 0 1 2 r begin 3 r 4 y 5 G 6 o 7 end
Deque<char> D Illustrated (11) §content_size = 8 §D. push_back(‘A’) §D. size() = (0 – 2 + 8) % 8 content 0 end 1 2 r begin 3 r 4 y 5 G 6 o 7 A
Deque<char> D Illustrated (12) §content_size = 8 §D. push_back(‘r’) §D. size() = (1 – 2 + 8) % 8 content 0 r 1 2 r end begin 3 r 4 y 5 G 6 o 7 A
Deque<char> D Illustrated (13) §D. size() == content_size – 1 §Now what? § § Return full or Double the capacity (as with Vector). content 0 r 1 2 r end begin 3 r 4 y 5 G 6 o 7 A
A Graphic Model of a Queue Tail: All new items are added on this end 86 Head: All items are deleted from this end
Operations on Queues §Insert(item): (also called enqueue) § It adds a new item to the tail of the queue §Remove( ): (also called delete or dequeue) § It deletes the head item of the queue, and returns to the caller. If the queue is already empty, this operation returns NULL §get. Head( ): § Returns the value in the head element of the queue (peek. Head()) §get. Tail( ): § Returns the value in the tail element of the queue (peek. Tail()) §is. Empty( ) § Returns true if the queue has no items §size( ) § 87 Returns the number of items in the queue
Examples of Queues §An electronic mailbox is a queue § The ordering is chronological (by arrival time) §A waiting line in a store, at a service counter, on a one-lane road §Equal-priority processes waiting to run on a processor in a computer system 88
Queues §A stack is LIFO (Last-In First Out) structure. §In contrast, a queue is a FIFO (First-In First -Out ) structure. §A queue is a linear structure for which items can be only inserted at one end and removed at another end.
Queue Operations Enqueue(X) – place X at the rear of the queue. Dequeue() -- remove the front element and return it. Front() -return front element without removing it. Is. Empty() -return TRUE if queue is empty, FALSE otherwise
How head and tail Change §head increases by 1 after each dequeue( ) §tail increases by 1 after each enqueue( ) head tail Now: After enqueue: 49 48 47 4 3 tail 2 1 0 head 49 48 47 4 3 2 1 head 0 2 1 0 tail After dequeue: 91 49 48 47 4 3
A Circular Queue §Allow the head (and the tail) to be moving targets §When the tail end fills up and front part of the array has empty slots, new insertions should go into the front end head tail 49 48 47 4 3 2 1 0 §Next insertion goes into slot 0, and tail tracks it. The insertion after that goes into a lot 1, etc. 92
Illustration of Circular Queues §Current state: head 4 3 49 48 47 tail §After One Call to enqueue() head 49 48 47 4 3 2 2 head 93 48 47 4 3 0 tail §After One Call to enqueue() 49 1 1 0 tail 2 1 0
Numerics for Circular Queues §head increases by (1 modulo capacity) after each dequeue( ): head = (head +1) % capacity; §tail increases by (1 modulo capacity) after each enqueue( ): tail = (tail +1) % capacity; 94
Array-Based Implementation of a Queue §Let queue[0] be the front § front. Index, back. Index are indices of front and back §If we insist queue[0] is front § Must shift entries when we remove the front §Instead move front. Index § § 95 Problem then is array can become full But now beginning of array could be empty and available for use
Array-Based Implementation of a Queue An array that represents a queue without shifting its entries: (a) initially; (b) after removing the front twice; 96
Implementing a Queue #define TYPE int typedef struct { int front, rear, number. Items; int Capacity; TYPE *items; } Queue; void initialize(Queue *s, int size) {s->rear=0; s->front=0; s->number. Items=0; s->Capacity=size; s->items=malloc(size*sizeof(TYPE)); } void enqueue(Queue *s, TYPE value) { s->items[s->rear++]=value; s->rear%=s->Capacity; s->number. Items++; } TYPE dequeue(Queue *s) { s->front%=s->Capacity; /*can do better? */ s->number. Items--; return s->items[s->front++]; } 97
Implementing a Queue #define TYPE int typedef struct { int front, rear, number. Items; int Capacity; TYPE *items; } Queue; int isfull(Queue *s) { return s->number. Items==s->Capacity? 1: 0 ; } int isempty(Queue *s) { return s->number. Items==0? 1: 0; } void dispose(Queue *s) {free(s->items); } 98
Implementing a Queue #define TYPE int typedef struct { int front, rear, number. Items; int Capacity; TYPE *items; } Queue; int main() { Queue q; initialize(&q, 100); int i; for (i=0; i<q. Capacity+10; i++) if (!isfull(&q)) enqueue(&q, i); while (!isempty(&q)) printf("[%d]", dequeue(&q)); dispose(&q); enqueue(&q, 7); /// ERROR return 0; } [0][1][2][3][4]. . . [98][99] 99
Breadth First Search §Problem n Find a shortest path from start to goal start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (2) §Queue 1 push start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (3) §Queue pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (4) §Queue 2 3 4 pop pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (5) §Queue 3 4 pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (6) §Queue 3 4 5 push 6 push start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (7) §Queue 4 5 6 Pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (8) §Queue 4 5 6 7 8 Push start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (9) §Queue 5 6 7 8 Pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (10) §Queue 6 7 8 Pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (11) §Queue 7 8 Pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (12) §Queue 7 8 9 Push start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (13) §Queue 8 9 Pop start 1 5 2 3 4 6 7 8 9 10 goal 11 12
Breadth First Search (14) §Queue 8 9 10 Push start 1 5 2 3 4 6 7 8 9 10 goal 11 12
- Slides: 113