杭州师范大学信息科学与工程学院 袁贞明 STACKS AND QUEUES and their applications
3.3 The Stack Abstract Data Type Stack An ordered list in which insertions and deletions are made at one end called the top only. Last - In - First - Out ( L I F O ) Stack S = (a 0, …, a n-1 ) a 0 -- the bottom element a n-1 -- the top element 杭州师范大学信息科学与工程学院 袁贞明
Stack Abstract Data Type Structure Stack is Object: a finite ordered list with zero or more elements. Functions: for all stack ∈ Stack, item ∈ element, max_stack_size ∈ positive integer Stack CreateS(max_stack_size) ::= create an empty stack whose maximum size is max_stack_size Boolean IsFull(stack, max_stack_size) ::= if ( number of elements in stack == max_stack_size ) return TRUE else return FALSE Stack Push(stack, item) ::= if ( IsFull(stack) ) stack_full else insert item into top of stack and return Boolean IsEmpty(stack) ::= if ( stack == CreateS(max_stack_size) ) return TRUE else return FALSE Element Pop(stack) ::= if ( IsEmpty(stack) ) return else remove and return the item on the top of the stack 杭州师范大学信息科学与工程学院 袁贞明
3.3.2 Dynamically Linked Stacks Linked Stacks STACK NULL element top Push: element top temp temp->next = S->next S->next = temp Read Figure 3.38-Figure 443 on p about implementation of push and pop Pop: temp = S->next S->next = S->next->next S item = temp->element free ( temp ) item return item Question: How to represent n stacks? Answer: Stack top [ n ] ; / S …… element next element 杭州师范大学信息科学与工程学院 袁贞明
Array Implementation of Stacks Representation Stack CreateS ( max_stack_size ) ::= #define MAX_STACK_SIZE 100 /*maximum stack size */ typedef struct { int key; /* other fields */ } element; element stack [ MAX_STACK_SIZE ]; int top = -1; Operations Boolean IsEmpty(stack) ::= top < 0; Boolean IsFull(stack) ::= top >= max_stack_size - 1; Add to a stack Delete from a stack 杭州师范大学信息科学与工程学院 袁贞明
3.4 The Queues Abstract Data Type Queue An ordered list in which all insertions take place at one end and all deletions take place at the opposite end. First - in - First - Out (FIFO) queue Q = (a 0, …, a n-1 ) a 0 -- the front element a n-1 -- the rear 杭州师范大学信息科学与工程学院 袁贞明
Queue Abstract Data Type structure Queue is object: a finite ordered list with zero or more elements. functions: for all queue ∈ Queue, item ∈ element, max_queue_size ∈ positive integer Queue CreateQ(max_queue_size) ::= create an empty queue whose maximum size is max_queue_size Boolean IsFullQ(queue, max_queue_size) ::= if ( number of elements in queue == max_queue_size ) return TRUE else return FALSE Queue AddQ(queue, item) ::= if ( IsFullQ(queue) ) queue_full else insert item at rear of queue and return queue Boolean IsEmptyQ(queue) ::= if ( queue == CreatQ(max_queue_size) ) return TRUE else return FALSE Element DeleteQ( queue) ::= if ( IsEmptyQ( queue ) ) return else remove and return the item at front of queue 杭州师范大学信息科学与工程学院 袁贞明
Representation and Operations Representation Queue CreateQ ( max_queue_size ) ::= #define MAX_QUEUE_SIZE 100 /*maximum queue size */ typedef struct { int key; /* other fields */ } element; element queue [ MAX_QUEUE_SIZE ]; int rear = -1; int front = -1; Operations Boolean IsEmptyQ(queue) ::= front == rear; Boolean IsFullQ(queue) ::= rear == max_queue_size - 1; Add to a queue Delete from a queue 杭州师范大学信息科学与工程学院 袁贞明
Circular Queues Are you kidding? Of course I do! Do you have a better idea? [ 0 ] [ 1 ] [ 2 ][ 3 ] [ 4 ] [ 5 ] front rear Push Job 1 Push Job 2 Push Job 3 Pop Job 1 Push Job 4 Push Job 5 Push Job 6 Push Job 7 Job 1 front rear Job 2 rear Job 3 rear front rear Job 4 rear Job 5 rear Job 6 The queue is full The queue is full Note: We should rotate rear and front before we push or pop any item. Question: Why is the queue announced full while there is still a free space left? rear 杭州师范大学信息科学与工程学院 袁贞明
Linked Queues QUEUE NULL item front rear PushQ: item temp rear->next = temp temp->next = NULL NULL rear = temp rear PopQ: temp = front temp front = temp->next front item = temp->item item free ( temp ) return item Read Program 4.8 and Program 4.9 on p.151 about implementation of pushQ and popQ Question: How to represent n queues? Answer: queue_pointer front[n], rear[n]; 杭州师范大学信息科学与工程学院 袁贞明
Multiple Stacks and Queues Definition #define MEMORY_SIZE 100 /* size of memory */ #define MAX_STACKS 10 /* max number of stacks plus 1*/ element memory [ MEMORY_SIZE ]; /* global memory declaration */ int top [ MAX_STACKS ]; int boundary [ MAX_STACKS ]; int n ; /* number of stacks entered by the user */ All stacks are empty and divided into roughly equal segments top [ 0] = boundary [ 0] = -1; for ( i = 1; i < n; i ++ ) top [ i ] = boundary [ i ] = (MEMORY_SIZE / n ) * i; boundary [n ] = MEMORY_SIZE -1; 杭州师范大学信息科学与工程学院 袁贞明
杭州师范学院信息工程学院 袁贞明 Add an item to the stack stack_no Delete an item from the stack stack_no void add(int i, element item) { /* add an item to the ith stack */ if ( top[i] == boundary[i+1] ) stack_full(i); memory[++top[i]] = item; } void add(int i, element item) { /* add an item to the ith stack */ if ( top[i] == boundary[i+1] ) stack_full(i); memory[++top[i]] = item; } element delete(int i) { /* remove top element from the ith stack */ if ( top[i] == boundary[i] ) return stack_empty(i); return memory[top[i] -- ]; } element delete(int i) { /* remove top element from the ith stack */ if ( top[i] == boundary[i] ) return stack_empty(i); return memory[top[i] -- ]; } ! Configuration when stack i meet stack i =1, but the memory is not full b[0] t[0] b[1] t[1] b[i] t[i] t[i+1] t[j] b[j+1] b[n] b[i+1] b[i+2]
We can design stack_full so that we can add elements to this stack untill the array is full in the following way: (i) create a space between stack stack_no and stack_no+1. determine the least j ( stack_no < j < n )such that there is free space between stack j and j + 1 ( top [j ] < boundary[ j + 1 ] ). If there is such a j, then move stack_no +1, stack_no +2,…, j one position to right. (ii)create a space between stack stack_no and stack_no+1. look to the left of stack_no, Find the largest j such that 0 <= j < stack_no and there is space between j and j +1 (top [j] < boundary [j + 1]). If there is such a j, move stacks j, j+1,,……, stack_no one space to left. (iii) If there is no j satisfying either condition (i) or (ii). then all MEMORY_SIZE spaces of memory are utilized and there is no free space. In this case stack_full determinate with an error message. 杭州师范大学信息科学与工程学院 袁贞明
Application of Stack - Balancing Symbol Check whether everything is balanced, every right brace, bracket, and parenthesis must correspond to its left counterpart ( ) [ ] { } Make an empty stack. Read characters until end of file. If the character is an opening symbol, push it onto the 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 end of file, if the stack is not empty report an error. 杭州师范大学信息科学与工程学院 袁贞明
杭州师范学院信息工程学院 袁贞明 Evaluation Of Expressions Token Operatorprecedenceassociativity ( ) [ ] -> function call array element struct or union 17 left-to-right increment.,decre. postfix 16left-to-right ! ^ -- + & * sizeof decrement., incre. prefix logical not one's complement unaey minus or plus address or indirection size ( in bytes) 15right-to-left (type)type cast 14right-to-left = += -=assignment 2right-to-left comma 1left-to-right 〖 Example 〗 An infix expression: a b c d e A prefix expression: a b c d e A postfix expression: a b c d e operand operator with the highest precedence
(1) Evaluating Postfix Expression infix Postfix * * + a * b + 5a b * 5 + ( ) * * a * b / ca b * c / ((a/(b-c+d))*(e-a)*cabc-d+/ea-*c* a/b-c+d*e-a*cab/c-de*+ac*- 杭州师范大学信息科学与工程学院 袁贞明
〖 Example 〗 6 2 3 4 2 = ? top Get token: 6 ( operand ) top 6 Get token: 2 ( operand ) top 2 Get token: ( operator ) 2 6= 3 top 3 Get token: 3 ( operand ) 3 top Get token: ( operator ) 3 top 3 = 0 0 top Get token: 4 ( operand ) top 4 Get token: 2 ( operand ) top 2 Get token: ( operator ) top 2 4 = 8 8 top Get token: ( operator ) top 8 0 = 8 8 top Pop: 8 top 8 杭州师范大学信息科学与工程学院 袁贞明
Program Definition #define MAX_STACK_SIZE 100 /* maximum stack size */ #define MAX_EXPR_SIZE 100 /* max size of expression*/ typedef enum ( lparen, rparen, plus, minus, times, divide, mod, eos, operand ) precedence; int stack [ MAX_STACK_SIZE ]; /* global stack */ char expr [ MAX_EXPR_SIZE ]; /* input string */ Example infix expression = 6 / * 2 postfix expression = 6 2 / * + Token [0] [1] [2] StackTop 62/3-42*+62/3-42* /2 6/2 3 6/2-3 6/ / /2-3 4*2 6/2-3+4* 杭州师范大学信息科学与工程学院 袁贞明
Function to evaluate a postfix expression #define MAX_STACK_SIZE 100 /* maximum stack size */ #define MAX_EXPR_SIZE 100 /* max size of expression*/ typedef enum { lparen, rparen, plus, minus, times, divide, mod, eos, operand } precedence; int stack [ MAX_STACK_SIZE ]; /* global stack */ char expr [ MAX_EXPR_SIZE ]; /* input string */ int eval ( void ) { /* evaluate a postfix expression*/ precedence token; char symbol; /* original character of token */ int op1, op2; /* operands */ int n = 0;/* counter for the expression string */ int top = 1; token = get_token( &symbol, &n ); /* get one symbol and token type from expr [ n ] */ 杭州师范大学信息科学与工程学院 袁贞明
杭州师范学院信息工程学院 袁贞明 Function to evaluate a postfix expression while ( token != eos ) { /* while it’s not the end of expr */ if ( token == operand ) push (&top, symbol ’0’); /* push the number into stack */ else { op2 = pop ( &top ); /* pop two operands */ op1 = pop ( &top ); switch ( token ) { /* perform operation and push result */ case plus: push ( &top, op1 + op2 ); break; case minus: push ( &top, op1 op2 ); break; case times: push ( &top, op1 op2 ); break; case divide: push ( &top, op1 / op2); break; case mod: push ( &top, op1 % op2 ); } /* end switch */ } /* end else */ token = get_token (&symbol, &n); /* get the next token */ } /* end while-loop */ return pop ( &top ); /* return result */ }
杭州师范学院信息工程学院 袁贞明 Function to get a token from the input string precedure get_token(char *symbol, int *n) { /* get the next token, symbol is the character representation, which is returned, the token is represented by its enumerated value, which is returned in the function name */ *symbol = expr[(*n)++]; switch ( *symbol ) { case '( ' : return lparen; case ' )' : return rparen; case '+' : return plus; case '-' : return minus; case '/ ' : return divide; case '*' : return times; case '%' : return mod; case ' ' : return eos; default : return operand;/* no error checking, default is operand */ } precedure get_token(char *symbol, int *n) { /* get the next token, symbol is the character representation, which is returned, the token is represented by its enumerated value, which is returned in the function name */ *symbol = expr[(*n)++]; switch ( *symbol ) { case '( ' : return lparen; case ' )' : return rparen; case '+' : return plus; case '-' : return minus; case '/ ' : return divide; case '*' : return times; case '%' : return mod; case ' ' : return eos; default : return operand;/* no error checking, default is operand */ }
(2) Infix To Postfix Algorithm (infix to postfix) 1. Full paranthesize the expression 2. Move all binary operators so that they replace their corresponding right parentheses. 3. Delete all parentheses. a / b - c + d * e - a * c ((((a / b ) - c ) + ( d * e )) - a * c )) ---> a b / c - d e * + a c * -- 【 example 】 Simple expression (a + b * c) Token Stack [0] [1] [2] Topoutput a + b * c eos + + * 0 1 a ab abc abc*+ 杭州师范大学信息科学与工程学院 袁贞明
【 example 】 parenthesized expression (a * (b + c) * d) Token Stack [0] [1] [2] TopOutput a * ( b + c ) * d eos * * ( * ( + * a ab abc abc+ abc+* abc+*d abc+*d* 杭州师范大学信息科学与工程学院 袁贞明
杭州师范学院信息工程学院 袁贞明 Program postfix O(n) void postfix(void) { char symbol; precedence token; int n = 0; int top = 0;/* place eos on stack */ stack[0] = eos; for ( token = get_token(&symbol, &n); token != eos; token =get_token(&symbol,&n) ) { if ( token == operand ) printf("%c",symbol); else if ( token == rparen ) {/* unstack tokens until left parenthesis */ while ( stack[top] != lparen ) print_token(delete(&top)); delete (&top);/* discard the left parenthesis */ } else { while ( isp[stack[top]] >= icp[token] ) printf_token(delete(&top)); add(&top, token); } while ( (token=delete(&top)) != eos ) print_token(token); printf("\n"); } void postfix(void) { char symbol; precedence token; int n = 0; int top = 0;/* place eos on stack */ stack[0] = eos; for ( token = get_token(&symbol, &n); token != eos; token =get_token(&symbol,&n) ) { if ( token == operand ) printf("%c",symbol); else if ( token == rparen ) {/* unstack tokens until left parenthesis */ while ( stack[top] != lparen ) print_token(delete(&top)); delete (&top);/* discard the left parenthesis */ } else { while ( isp[stack[top]] >= icp[token] ) printf_token(delete(&top)); add(&top, token); } while ( (token=delete(&top)) != eos ) print_token(token); printf("\n"); }
A Mazing Problem O(mp) entrance exit A Maze 1. Representing the Maze position = maze = maze [ row ] [ col ] = 1 if blocked 0 if open maze border = 1 entrance =, exit = maze [ m+2 ] [ p+2 ] 杭州师范大学信息科学与工程学院 袁贞明
Directions typedef struct { short int vert; short int horiz; } offesets; offesets move [ 8 ]; /*array of moves for direction*/ NW [row 1][col 1] N [row 1][col] NE [row 1][col+1] W [row][col 1] [row][col] E [row][col+1] SW [row+1][col 1] S [row+1][col] SE [row+1][col+1] next_row = row + move[dir].vert; next_col = col + move[dir].horiz; next_row = row + move[dir].vert; next_col = col + move[dir].horiz; 杭州师范大学信息科学与工程学院 袁贞明
Sketch of the Idea top top top top top top top Note: Since each position is visited at most once, we need another 2-D array mark [ ][ ] for the record. mark [row][col] = 1 checked 0 not checked MAX_STACK_SIZE m p top 杭州师范大学信息科学与工程学院 袁贞明
Algorithm initialize a stack to the maze's entrance coordinates and direction to north; while ( stack is not empty ) { = delete from top of stack; while ( there are more moves from current position ) { = coordinates of next move; dir = direction of move; if ( (next_row == EXIT_ROW) && (next_col == EXIT_COL) ) success; if ( maze[next_row][next_col] == 0 && mark[next_row][next_col] == 0 ) { /* legal move and haven't been there */ mark[next_row][next_col] = 1; /* save current position and direction */ add to the top of the stack; row = next_row; col = next_col; dir = north; } //if }// while } printf("No path found\n"); initialize a stack to the maze's entrance coordinates and direction to north; while ( stack is not empty ) { = delete from top of stack; while ( there are more moves from current position ) { = coordinates of next move; dir = direction of move; if ( (next_row == EXIT_ROW) && (next_col == EXIT_COL) ) success; if ( maze[next_row][next_col] == 0 && mark[next_row][next_col] == 0 ) { /* legal move and haven't been there */ mark[next_row][next_col] = 1; /* save current position and direction */ add to the top of the stack; row = next_row; col = next_col; dir = north; } //if }// while } printf("No path found\n"); 杭州师范大学信息科学与工程学院 袁贞明
C Program Definition #define MAX_STACK_SIZE 100 /* maximum stacksize */ typedef struct { short int row; short int col; short int dir; } element; element stack[ MAX_STACK_SIZE ]; 杭州师范大学信息科学与工程学院 袁贞明
杭州师范学院信息工程学院 袁贞明 Maze search function void path(void) { /* output a path through the maze if such a path exists */ int i, row, col, next_row, next_col, dir, found = FALSE; element position; mark[1][1] = 1; top = 0; stack[0].row = 1; stack[0].col = 1; stack[0].dir = 1; while ( top > -1 && !found ) { position = delete(&top); row = position.row; col = position.col; dir = position.dir; while ( dir < 8 && !found ) { /*move in direction dir */ next_row = row + move[dir].vert; next_col = col + move[dir].horiz; if ( next_row == EXIT_ROW && next_col == EXIT_COL ) found = TRUE; else if ( !maze[next_row][next_col] && !mark[next_row][next_col] ) { mark[next_row][next_col] = 1; position.row = row; position.col = col; position.dir = ++dir; add(&top, position); row = next_row; col = next_col; dir = 0; } else ++dir; } if ( found ) { printf ("The path is:\n"); printf ("row col\n"); for ( i = 0; i <= top; i++ ) printf ("%2d%5d", stack[i].row, stack[i].col); printf ("%2d%5d\n",row,col); printf ("%2d%5d\n',EXIT_ROW,EXIT_COL); } else printf ("The maze does not have a path\n"); }
Homework - exercises P a,b Write a program to check for balancing symbols in the following languages: Pascal, C P Write routines to implement two stacks using only one array. Your stack routines should not declare an overflow unless every slot in the array is used. P Write routines to support the deque that take O(1) time per operation. 杭州师范大学信息科学与工程学院 袁贞明