CHAPTER 3 STACKS AND QUEUES All the programs

  • Slides: 54
Download presentation
CHAPTER 3 STACKS AND QUEUES All the programs in this file are selected from

CHAPTER 3 STACKS AND QUEUES All the programs in this file are selected from Ellis Horowitz, Sartaj Sahni, and Susan Anderson-Freed “Fundamentals of Data Structures in C”, 1/e, Computer Science Press, 1992, 2/e, Silicon press, 2008. CHAPTER 3 1

Token Operator Precedence Associativity () [] ->. Function call Array element Struct or union

Token Operator Precedence Associativity () [] ->. Function call Array element Struct or union member 17 17 17 Left-to-right i-- i++ Increment, decrement 16 Left-to-right --I ++i ! ~ - + & * Sizeof Decrement, increment Logical not One’s complement Unary minus or plus Address or indirection Size (in bytes) 15 Right- to-left (type) Type cast 14 Right- to-left * / % Multiplicative 13 Left-to-right + - Binary add or subtract 12 Left-to-right << >> Shift 11 Left-to-right CHAPTER 3 2

> >= < <= == != Relational 10 Equality 9 & Bitwise and 8

> >= < <= == != Relational 10 Equality 9 & Bitwise and 8 ^ Bitwise exclusive or 7 | Bitwise or 6 && Logical and 5 || Logical or 4 ? : Conditional 3 = += -= /= *= Assignment %= <<= >>= &= ^= |=. comma 2 1 *Figure 3. 12: Precedence hierarchy for C CHAPTER 3 Left-toright Left-toright Right- toleft Left-toright (p. 130) 3

Stack (stack: a Last-In-First-Out (LIFO) list ) l Stack ¡ An ordered list ¡

Stack (stack: a Last-In-First-Out (LIFO) list ) l Stack ¡ An ordered list ¡ Insertions and deletions are made at one end, called top l Illustration push E top D C top C C B B top B B A top A A Inserting and deleting elements in a stack CHAPTER 3 pop D top C B A 4

Some stack applications l Implementing recusive call l Expression evaluation ¡Infix to postfix ¡Postfix

Some stack applications l Implementing recusive call l Expression evaluation ¡Infix to postfix ¡Postfix evaluation l Maze problem l Breadth First Search l …… CHAPTER 3 5

an application of stack: stack frame of function call fp fp: a pointer to

an application of stack: stack frame of function call fp fp: a pointer to current stack frame al fp main system stack before a 1 is invoked system stack after a 1 is invoked (a) (b) *Figure 3. 2: System stack after function call a 1 (p. 109) CHAPTER 3 6

abstract data type for stack structure Stack is objects: a finite ordered list with

abstract data type for stack structure Stack is objects: a finite ordered list with zero or more elements. functions: for all stack Stack, item element, max_stack_size positive integer Stack Create. S(max_stack_size) : : = create an empty stack whose maximum size is max_stack_size Boolean Is. Full(stack, max_stack_size) : : = if (number of elements in stack == max_stack_size) return TRUE else return FALSE Stack Add(stack, item) : : = if (Is. Full(stack)) stack_full else insert item into top of stack and return CHAPTER 3 7

Boolean Is. Empty(stack) : : = if(stack == Create. S(max_stack_size)) return TRUE else return

Boolean Is. Empty(stack) : : = if(stack == Create. S(max_stack_size)) return TRUE else return FALSE Element Delete(stack) : : = if(Is. Empty(stack)) return else remove and return the item on the top of the stack. *ADT 3. 1: Abstract data type Stack (p. 109) CHAPTER 3 8

Implementation: using array Stack Create. S(max_stack_size) : : = #define MAX_STACK_SIZE 100 /* maximum

Implementation: using array Stack Create. S(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; Boolean Is. Empty(Stack) : : = top< 0; Boolean Is. Full(Stack) : : = top >= MAX_STACK_SIZE-1; CHAPTER 3 9

Add to a stack void add(int *top, element item) { if (*top >= MAX_STACK_SIZE-1)

Add to a stack void add(int *top, element item) { if (*top >= MAX_STACK_SIZE-1) { stack_full( ); return; } stack[++*top] = item; } *program 3. 1: Add to a stack (p. 111) CHAPTER 3 10

Delete from a stack element delete(int *top) { if (*top == -1) return stack_empty(

Delete from a stack element delete(int *top) { if (*top == -1) return stack_empty( ); /* returns and error key */ return stack[(*top)--]; } *Program 3. 2: Delete from a stack (p. 111) CHAPTER 3 11

Queue (Queue: a First-In-First-Out (FIFO) list) l Queue ¡ An ordered list ¡ All

Queue (Queue: a First-In-First-Out (FIFO) list) l Queue ¡ An ordered list ¡ All insertions take place at one end, rear ¡ All deletions take place at the opposite end, front l Illustration A rear front B A C rear B front A CHAPTER 3 D rear C B front A rear D C front B rear front 12

Some queue applications l Job scheduling l Event list in simulator l Server and

Some queue applications l Job scheduling l Event list in simulator l Server and Customs l …… CHAPTER 3 13

Application: Job scheduling *Figure 3. 5: Insertion and deletion from a sequential queue (p.

Application: Job scheduling *Figure 3. 5: Insertion and deletion from a sequential queue (p. 117) CHAPTER 3 14

Queue (ADT) structure Queue is objects: a finite ordered list with zero or more

Queue (ADT) structure Queue is objects: a finite ordered list with zero or more elements. functions: for all queue Queue, item element, max_ queue_ size positive integer Queue Create. Q(max_queue_size) : : = create an empty queue whose maximum size is max_queue_size Boolean Is. Full. Q(queue, max_queue_size) : : = if(number of elements in queue == max_queue_size) return TRUE else return FALSE Queue Add. Q(queue, item) : : = if (Is. Full. Q(queue)) queue_full else insert item at rear of queue and return queue CHAPTER 3 15

Boolean Is. Empty. Q(queue) : : = if (queue ==Create. Q(max_queue_size)) return TRUE else

Boolean Is. Empty. Q(queue) : : = if (queue ==Create. Q(max_queue_size)) return TRUE else return FALSE Element Delete. Q(queue) : : = if (Is. Empty. Q(queue)) return else remove and return the item at front of queue. *ADT 3. 2: Abstract data type Queue (p. 115) CHAPTER 3 16

Implementation 1: using array Queue Create. Q(max_queue_size) : : = # define MAX_QUEUE_SIZE 100/*

Implementation 1: using array Queue Create. Q(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; Boolean Is. Empty(queue) : : = front == rear Boolean Is. Full. Q(queue) : : = rear == MAX_QUEUE_SIZE-1 CHAPTER 3 17

Add to a queue void addq(int *rear, element item) { if (*rear == MAX_QUEUE_SIZE_1)

Add to a queue void addq(int *rear, element item) { if (*rear == MAX_QUEUE_SIZE_1) { queue_full( ); return; } queue [++*rear] = item; } *Program 3. 3: Add to a queue (p. 108) (1/e) CHAPTER 3 18

Delete from a queue element deleteq(int *front, int rear) { if ( *front ==

Delete from a queue element deleteq(int *front, int rear) { if ( *front == rear) return queue_empty( ); /* return an error key */ return queue [++ *front]; } *Program 3. 4: Delete from a queue(p. 108) (1/e) CHAPTER 3 19

Implementation 2: regard an array as a circular queue front: one position counterclockwise from

Implementation 2: regard an array as a circular queue front: one position counterclockwise from the first element rear: current end [2] [3] [2] J 2 [1] [4] J 1 [0] [5] front = 0 rear = 0 Empty circular Queue [3] J 3 [4] [5] front = 0 rear = 3 Nonempty circular queue *Figure 3. 6: Empty and nonempty circular queues (p. 117) CHAPTER 3 20

Problem: one space is left when queue is full [3] J 2 J 3

Problem: one space is left when queue is full [3] J 2 J 3 J 4 [4] [1] J 1 J 5 [0] [5] [2] J 8 [1] J 7 J 6 [0] front = 0 rear = 5 [3] J 9 [4] J 5 [5] front = 4 rear = 3 Full Circular queue (waste one space ) *Figure 3. 7: Full circular queues and then we remove the item (p. 110) CHAPTER 3 (1/e) 21

l 避免出現rear=front 而無法分辨circular queue是滿的? 還是空的? 所以最多存放 Maxsize -1個空間 l 或是加入一個COUNT變數表示queue的 個數 COUNT=0 (空) COUNT=Maxsize

l 避免出現rear=front 而無法分辨circular queue是滿的? 還是空的? 所以最多存放 Maxsize -1個空間 l 或是加入一個COUNT變數表示queue的 個數 COUNT=0 (空) COUNT=Maxsize ( 滿) CHAPTER 3 22

Add to a circular queue void addq(int front, int *rear, element item) { *rear

Add to a circular queue void addq(int front, int *rear, element item) { *rear = (*rear +1) % MAX_QUEUE_SIZE; if (front == *rear) /* reset rear and print error */ return; } queue[*rear] = item; } *Program 3. 5: Add to a circular queue (p. 110) (1/e) CHAPTER 3 23

Delete from a circular queue element deleteq(int* front, int rear) { element item; if

Delete from a circular queue element deleteq(int* front, int rear) { element item; if (*front == rear) return queue_empty( ); /* queue_empty returns an error key */ *front = (*front+1) % MAX_QUEUE_SIZE; return queue[*front]; } *Program 3. 6: Delete from a circular queue (p. 111) (1/e) CHAPTER 3 24

Evaluation of Expressions l Evaluating a complex expression in computer ¡((rear+1==front)||((rear==Max. Queue. Size 1)&&!front))

Evaluation of Expressions l Evaluating a complex expression in computer ¡((rear+1==front)||((rear==Max. Queue. Size 1)&&!front)) ¡x= a/b- c+ d*e- a*c l Figuring out the order of operation within any expression ¡A precedence hierarchy within any programming language ¡See Figure 3. 12 CHAPTER 3 25

Evaluation of Expressions (Cont. ) l Ways to write expressions ¡Infix (standard) ¡Prefix ¡Postfix

Evaluation of Expressions (Cont. ) l Ways to write expressions ¡Infix (standard) ¡Prefix ¡Postfix lcompiler, a parenthesis-free notation Infix 2+3*4 a*b+5 (1+2)*7 a*b/c ((a/(b-c+d))*(e-a)*c a/b-c+d*e-a*c CHAPTER 3 Postfix 2 3 4*+ ab*5+ 1 2+7* ab*c/ abc-d+/ea-*c* ab/c-de*+ac*26

Evaluation of Postfix Expressions • Left-to-right scan Postfix expression, 1) Stack operands until find

Evaluation of Postfix Expressions • Left-to-right scan Postfix expression, 1) Stack operands until find an operator, 2) Meet operator, remove correct operands for this operator, 3) Perform the operation, 4) Stack the result • Remove the answer from the top of stack CHAPTER 3 27

Evaluation of Postfix Expressions Token 6 2 / 3 4 2 * + Stack

Evaluation of Postfix Expressions Token 6 2 / 3 4 2 * + Stack [1] [2] [0] 6 6 2 6/2 3 6/2 -3 4*2 6/2 -3+4*2 2 Top 0 1 0 1 2 1 0 Postfix evaluation of 6 2/3 -4 2*+ CHAPTER 3 28

Assumptions: operators: +, -, *, /, % operands: single digit integer #define MAX_STACK_SIZE 100

Assumptions: operators: +, -, *, /, % operands: single digit integer #define MAX_STACK_SIZE 100 #define MAX_EXPR_SIZE 100 /* max size of expression */ typedef enum{1 paran, rparen, plus, minus, times, divide, mod, eos, operand} precedence; int stack[MAX_STACK_SIZE]; /* global stack */ char expr[MAX_EXPR_SIZE]; /* input string */ CHAPTER 3 29

int eval(void) { precedence token; char symbol; int op 1, op 2; int n

int eval(void) { precedence token; char symbol; int op 1, op 2; int n = 0; /* counter for the expression string */ int top = -1; token = get_token(&symbol, &n); while (token != eos) { if (token == operand) add(&top, symbol-’ 0’); /* stack add */ exp: character array CHAPTER 3 30

else { /* remove two operands, perform operation, and return result to the stack

else { /* remove two operands, perform operation, and return result to the stack */ op 2 = delete(&top); /* stack delete */ op 1 = delete(&top); switch(token) { case plus: add(&top, op 1+op 2); break; case minus: add(&top, op 1 -op 2); break; case times: add(&top, op 1*op 2); break; case divide: add(&top, op 1/op 2); break; case mod: add(&top, op 1%op 2); } } token = get_token (&symbol, &n); } return delete(&top); /* return result */ } *Program 3. 9: Function to evaluate a postfix expression (p. 122) CHAPTER 3 31

precedence get_token(char *symbol, int *n) { *symbol =expr[(*n)++]; switch (*symbol) { case ‘(‘ :

precedence get_token(char *symbol, int *n) { *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; } } *Program 3. 10: Function to get a token from the input string (p. 123) CHAPTER 3 32

Infix to Postfix 1) Method I 1) Fully parenthesize the expression 2) Move all

Infix to Postfix 1) Method I 1) Fully parenthesize the expression 2) Move all binary operators so that they replace their corresponding right parentheses 3) Delete all parentheses l Examples: a/b-c+d*e-a*c ¡ ((((a/b)-c)+(d*e))-(a*c)), fully parentheses ¡ ab/c-de*+ac *+ *-, *- replace right parentheses and delete all parentheses l Disadvantage ¡ inefficient, two passes CHAPTER 3 33

Infix to Postfix l Method II 1) scan the infix expression left-to-right 2) output

Infix to Postfix l Method II 1) scan the infix expression left-to-right 2) output operand encountered 3) output operators depending on their precedence, i. e. , higher precedence operators first l Example: a+b*c, a+b*c simple expression Token Stack [0] [1] a + + b + * c + * eos Top Output -1 0 0 1 1 -1 a a ab ab abc*+ [2] CHAPTER 3 34

Infix to Postfix l Example: a*(b+c)*d , parenthesized expression Token Stack [0] a *

Infix to Postfix l Example: a*(b+c)*d , parenthesized expression Token Stack [0] a * * ( * b * + * c * ) * * * d * eos * [1] ( ( Output -1 0 1 1 2 2 0 0 a ab ab abc+*d abc+*d* [2] + + CHAPTER 3 Top 35

Infix to Postfix l Last two examples suggests a precedencebased scheme for stacking and

Infix to Postfix l Last two examples suggests a precedencebased scheme for stacking and unstacking operators ¡ isp (in-stack precedence) ¡ icp (in-coming precedence) precedence stack[Max. Stack. Size]; /* isp and icp arrays - index is value of precedence lparen, rparen, plus, minus, time divide, mod, eos */ static int isp[]= { 0, 19, 12, 13, 13, 0}; static int icp[]= {20, 19, 12, 13, 13, 0}; u See program 3. 11 - (n) CHAPTER 3 36

void postfix(void) { /* output the postfix of the expression. The expression string, the

void postfix(void) { /* output the postfix of the expression. The expression string, the stack, and top are global */ 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 ){ CHAPTER 3 37

/*unstack tokens until left parenthesis */ while (stack[top] != lparen) print_token(delete(&top)); delete(&top); /*discard the

/*unstack tokens until left parenthesis */ while (stack[top] != lparen) print_token(delete(&top)); delete(&top); /*discard the left parenthesis */ } else{ /* remove and print symbols whose isp is greater than or equal to the current token’s icp */ while(isp[stack[top]] >= icp[token] ) print_token(delete(&top)); f(n)= (g(n)) iff there exist positive add(&top, token); constants c 1, c 2, and n 0 such } that c 1 g(n) f(n) c 2 g(n) for all } while ((token = delete(&top)) != eos) n, n n 0. print_token(token); f(n)= (g(n)) iff g(n) is both an print(“n”); } (n) upper and lower bound on f(n). *Program 3. 11: Function to convert from infix to postfix (p. 126) CHAPTER 3 38

Infix Prefix a*b/c /*abc a/b-c+d*e-a*c -+-/abc*de*ac a*(b+c)/d-g -/*a+bcdg (1) evaluation (2) transformation *Figure 3.

Infix Prefix a*b/c /*abc a/b-c+d*e-a*c -+-/abc*de*ac a*(b+c)/d-g -/*a+bcdg (1) evaluation (2) transformation *Figure 3. 17: Infix and postfix expressions (p. 127) 後序優於中序: 去除運算子優先權, 結合性和括號 方便complier計算運算子的值, 掃描一次便可求結果 CHAPTER 3 39

Multiple stacks and queues Two stacks m[0], m[1], …, m[n-2], bottommost stack 1 m[n-1]

Multiple stacks and queues Two stacks m[0], m[1], …, m[n-2], bottommost stack 1 m[n-1] bottommost stack 2 More than two stacks (n) memory is divided into n equal segments boundary[stack_no] 0 stack_no < MAX_STACKS top[stack_no] 0 stack_no < MAX_STACKS CHAPTER 3 40

Initially, boundary[i]=top[i]. 0 1 boundary[ 0] top[ 0] [ m/n ] boundary[1] top[ 1]

Initially, boundary[i]=top[i]. 0 1 boundary[ 0] top[ 0] [ m/n ] boundary[1] top[ 1] 2[ m/n ] boundary[ 2] top[ 2] m-1 boundary[n] All stacks are empty and divided into roughly equal segments. *Figure 3. 18: Initial configuration for n stacks in memory [m]. (p. 140) CHAPTER 3 41

#define MEMORY_SIZE 100 /* size of memory */ #define MAX_STACK_SIZE 100 /* max number

#define MEMORY_SIZE 100 /* size of memory */ #define MAX_STACK_SIZE 100 /* max number of stacks plus 1 */ /* global memory declaration */ element memory[MEMORY_SIZE]; int top[MAX_STACKS]; int boundary[MAX_STACKS]; int n; /* number of stacks entered by the user */ p. 139 top[0] = boundary[0] = -1; for (i = 1; i < n; i++) top[i] =boundary[i] =(MEMORY_SIZE/n)*i; boundary[n] = MEMORY_SIZE-1; p. 139 CHAPTER 3 42

void add(int i, element item) { /* add an item to the ith stack

void add(int i, element item) { /* add an item to the ith stack */ if (top[i] == boundary [i+1]) stack_full(i); may have unused storage memory[++top[i]] = item; } *Program 3. 12: Add an item to the stack-no (p. 129) element delete(int i) { /* remove top element from the ith stack */ if (top[i] == boundary[i]) return stack_empty(i); return memory[top[i]--]; } *Program 3. 13: Delete an item from the stack-no (p. 130) CHAPTER 3 43

Find j, stack_no < j < n (往右) such that top[j] < boundary[j+1] or,

Find j, stack_no < j < n (往右) such that top[j] < boundary[j+1] or, 0 j < stack_no (往左) b[0] t[0] b[1] t[1] b[i] t[i+1] b[i+2] meet b=boundary, t=top t[j] b[j+1] b[n] 往左或右找一個空間 *Figure 3. 19: Configuration when stack i meets stack i+1, but the memory is not full (p. 141) CHAPTER 3 44

A Mazing Problem entrance 0 1 1 0 0 0 1 0 1 1

A Mazing Problem entrance 0 1 1 0 0 0 1 0 1 1 1 0 1 0 0 1 1 1 0 0 0 0 1 1 1 0 1 0 0 1 1 0 1 0 1 1 1 0 0 1 1 1 1 0 0 0 1 1 1 1 0 1 0 1 1 1 1 0 0 1 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 1 0 0 0 exit 1: blocked path 0: through path *Figure 3. 8: An example maze(p. 123) CHAPTER 3 45

a possible representation *Figure 3. 9: Allowable moves (p. 124) CHAPTER 3 46

a possible representation *Figure 3. 9: Allowable moves (p. 124) CHAPTER 3 46

a possible implementation typedef struct { short int vert; next_row = row + move[dir].

a possible implementation typedef struct { short int vert; next_row = row + move[dir]. vert; short int horiz; next_col = col + move[dir]. horiz; } offsets; offsets move[8]; /*array of moves for each direction*/ *Figure 3. 10 : Table of moves (p. 124) CHAPTER 3 47

Use stack to keep pass history #define MAX_STACK_SIZE 100 /* maximum stack size */

Use stack to keep pass history #define MAX_STACK_SIZE 100 /* maximum stack size */ typedef struct { short int row; short int col; short int dir; } element; element stack[MAX_STACK_SIZE]; CHAPTER 3 48

Initialize a stack to the maze’s entrance coordinates and direction to north; while (stack

Initialize a stack to the maze’s entrance coordinates and direction to north; while (stack is not empty){ /* move to position at top of stack */ <row, col, dir> = delete from top of stack; while (there are moves from current position) { <next_row, next_col > = 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) { CHAPTER 3 49

/* legal move and haven’t been there */ mark[next_row][next_col] = 1; /* save current

/* legal move and haven’t been there */ mark[next_row][next_col] = 1; /* save current position and direction */ add <row, col, dir> to the top of the stack; row = next_row; col = next_col; dir = north; } } } printf(“No path foundn”); *Program 3. 11: Initial maze algorithm (p. 126) CHAPTER 3 50

The size of a stack? 0 1 1 1 0 0 0 01 1

The size of a stack? 0 1 1 1 0 0 0 01 1 1 1 10 0 0 0 01 1 1 0 0 0 m*p *Figure 3. 11: Simple maze with a long path (p. 127) CHAPTER 3 51

void path (void) { /* output a path through the maze if such a

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; CHAPTER 3 52

if (next_row==EXIT_ROW && next_col==EXIT_COL) found = TRUE; else if ( !maze[next_row][next_col] && !mark[next_row][next_col] {

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; } } CHAPTER 3 53

if (found) { printf(“The path is : n”); printf(“row coln”); for (i = 0;

if (found) { printf(“The path is : n”); printf(“row coln”); for (i = 0; i <= top; i++) printf(“ %2 d%5 d”, stack[i]. row, stack[i]. col); printf(“%2 d%5 dn”, row, col); printf(“%2 d%5 dn”, EXIT_ROW, EXIT_COL); } else printf(“The maze does not have a pathn”); } *Program 3. 12: Maze search function (p. 128) CHAPTER 3 54