Chapter 3 of 'Fundamentals of Data Structures in C' covers the concepts of stacks and queues, detailing their abstract data types (ADTs), operations, and implementations. It explains the Last-In-First-Out (LIFO) nature of stacks and the First-In-First-Out (FIFO) nature of queues, along with practical applications and examples. Additionally, it introduces circular queues for more efficient data handling and discusses the evaluation of expressions using stacks.
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
0 ratings0% found this document useful (0 votes)
5 views61 pages
723597401stack and Data
Chapter 3 of 'Fundamentals of Data Structures in C' covers the concepts of stacks and queues, detailing their abstract data types (ADTs), operations, and implementations. It explains the Last-In-First-Out (LIFO) nature of stacks and the First-In-First-Out (FIFO) nature of queues, along with practical applications and examples. Additionally, it introduces circular queues for more efficient data handling and discusses the evaluation of expressions using stacks.
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF or read online on Scribd
You are on page 1/ 61
Chapter 3.
STACKS AND QUEUES
Horowitz, Sahni, and Anderson-Freed
Fundamentals of Data Structures in C 2nd Edition
Computer Science Press, 2008
Fall 2009 Course, Sungkyunkwan University
Hyunseung Choo
ch lece.skku.ac.kr
Copyright 2000-2009 Networking LaboratorStack Abstract Data Type
@ ADT stack Last-In-First-Out (LIFO)
> ordered list,insertions and deletions are made at one end
called the “top”
» Given stack S = (a, ---, a,.4)
* ag : bottom element
* a,,: top element
* a, on top of element a,,, (O» Inserting and deleting elements in stack
TE Wen eee meadStack Abstract Data Type
m Ex 3.1 [System stack]
> stack used by a program at run-time to process function calls
> Activation record(stack frame)
* initially contains only
* a pointer to the previous stack frame
* areturn address
> if this invokes another function
* local variables
» parameters of the invoking function
TE Wen eee meadStack Abstract Data Type
old frame pointer | fp
return address al
local variables
old frame pointer }— fp {old frame pointer
a return address main return address
(a) (b)
> system stack after function call
> run-time program simply creates a new stack frame
> (also for each recursive call)
TE ‘Networking Laboratory 4/61Stack Abstract Data Type
structure Stack is
objects: a finite ordered list with zero or
moreelements
functions:
for all stack < Stack, item < element,
max_stack_size « positive integer :
Stack CreateS(max_stack_size);
Boolean IsFull(stack,max_stack_size);
Stack Push(stack,item);
Boolean IsEmpty(stack);
Element Pop(stack);
TE Romer iicicenStack Abstract Data Type
m Implementing a stack
> using a one-dimensional array stack[MAX_STACK_SIZE]
#define MAX_STACK_SIZE 100
typedef struct {
int key;
} element;
element stack[MAX_STACK_SIZE];
int top = -1;
> structure element consists of only a key field, and we can add
fields to or modify to meet the requirements of the application
TE ernie p eric ierStack Abstract Data Type
m IsEmpty(stack)
return (top < 0);
g IsFull(stack)
return (top >= MAX_STACK_SIZE-1);
m Push(stack, item)
void push(int *ptop, element item) {
if (‘ptop >= MAX_STACK_SIZE - 1) {
stack_full();
return;
}
stack[++*ptop] = item;
}
TE enya ria ierStack Abstract Data Type
m@ Pop(stack)
element pop(int *ptop) {
if (*ptop == -1)
return stack_empty();
return stack[(‘ptop)--];
@ Application
> procedure calls/returns
> syntactic analyzer
> converting recursive procedures to
> non-recursive procedures
TE Wen eee mcdQueue Abstract Data Type
m ADT queue FIFO(First In First Out)
> ordered list
> all insertions are made at one end called “rear”
> all deletions are made at the other end called “front”
D|< rear
c|< rear | c D| < rear
B|< rear | B B c
A]< rear | A]< front | A]< front | A|~< front | B|< front
< front
> inserting and deleting elements in queue
> something is wrong in the figure ... what?
TE None p ee madQueue Abstract Data Type
a Implementing a queue
> a one-dimensional array, and two variables: front and rear
#tdefine MAX_QUEUE_SIZE 100
typedef struct {
int key;
F* other fields */
} element;
element queue[MAX_QUEUE_ SIZE];
int rear = -1;
int front
> IsEmptyQ(queue)
* return (front == rear);
> IsFullQ(queue)
* return rear == (MAX_QUEUE_SIZE-1);
TE ony etre ml)Queue Abstract Data Type
m Add to a queue
void addq(int *prear, element item) {
if (*prear == MAX_QUEUE SIZE - 1) {
queue _full();
return;
}
queue[++*prear] = item;
)
m Delete from a queue
element deleteq(int *pfront, int rear) {
if (*pfront == rear)
return queue_empty();
return queue[++"front];
ere ma
encirge
Note:
Tea icedQueue Abstract Data Type
m Ex 3.2 [job scheduling]
> creation of job queue
* in OS which does not use priorities, jobs are processed in the
order they enter the system
front [rear |Q[0] Q[1] QI2]__QI3]_|comments ]
- [-i queue is empty
a jo job 1 is added
a |i no 2 Job 2 is added
a |2 jn 2 2B job 3 is added
0 |2 R BB job 1 is deleted
1 [2 BB job 2 is deleted
insertion and deletion from a sequential queue
TE ero el racranQueue Abstract Data Type
mProblems
> queue gradually shifts to the right
> queue_full(rear==MAX_QUEUE_SIZE-1)
* signal does not always mean that there are MAX_QUEUE_SIZE
items in queue
* there may be empty spaces available
» data movement: O(MAX_QUEUE_SIZE)
* solutions : circular queue
TE ery el racranCircular Queues
COE Oe teenCircular Queues
@ More efficient queue representation
> regarding the array queue[MAX_QUEUE_SIZE] as circular
> initially front and rear to 0 rather than -1
» the front index always points one position counterclockwise
from the first element in the queue
>» the rear index points to the current end of the queue
TE ero elec ranCircular Queues
empty queue
(2]
front =
rear
3]
(4]
front = 0
rear = 3
> empty and nonempty circular queues
TE
eredCircular Queues
full queue full queue
> full circular queues
TE Were elias mia}Circular Queues
Implementing insertions and deletions
> use modulus operator for circular rotation
> circular rotation of the rear
*rear = (“rear + 1) % MAX_QUEUE_SIZE;
> circular rotation of the front
“front = (*front + 1) % MAX_QUEUE_SIZE;
TE ero elec raanCircular Queues
void addq(int front,int *rear,element item)
{
*rear = ("rear + 1) % MAX_QUEUE_ SIZE;
if (front == *rear) {
queue_full(rear);
/* reset rear and print error */
return;
}
queue[*rear] = item;
}
@ Add an item to a circular queue
> rotate rear before we place the item in queue[rear]
TE ero elec ranCircular Queues
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);
}
m Delete from a circular queue
TE Wey errrCircular Queues
g Tests for a full queue and an empty queue are the
same
» distinguish between the case of full and empty
1) permitting a maximum of MAX_QUEUE_SIZE - 1 rather than
MAX_QUEUE_SIZE elements, or
2) add new variable
m No data movement necessary
> ordinary queue: O(n)
> circular queue: O(1)
TE Wey errrHI
Mazing Problem:
(Skipped)
an Pn beneA Mazing Problem
m@ The representation of the maze
> two-dimensional array
» element 0 : open path
: barriers
> element 1
1
10001
10001
1 0
0
dL.
000
1
entrance
00
Io
oooot
1
10
1
00
00000
1
1011
1000
1
1
1
1
00
§
ig
5
8
Ey
4
5
ES
TEA Mazing Problem
N
[row-1] [col-1] [row-1]
NE
[col+1]
[row+1] [col-1] : ] | [row+1] [col+1]
sw SE
allowed move
TE Wey errrA Mazing Problem
@ [row][col] which is on border
> has only three neighbors
> surround the maze by a border of 1's
m@ m* pmaze
> requires (m+ 2) * (p + 2) array
> entrance position: [1][1]
> exit position: [m][p]
TE Wey errrA Mazing Problem
typedef struct {
short int vert;
short int horiz;
} offsets;
offsets move[8];
/* array of moves for each direction */
name dir moveldir].vert _ moveldir].horiz
N 0 “I
NE 1 “1
E 2
SE 3
s 4
5
6
1
sw
Ww
NW
Honmeeo
2
table of move
TE eer raeieA Mazing Problem
@ Position of next move
> move from current position
maze[row\[col]
> to the next position
maze[next_row|[next_col]
next_row = row + move{dir].vert;
next_col = col + movefdir].horiz;
TE Wey errrA Mazing Problem
m Maintain a second two-dimensional array, mark
> avoid returning to a previously tried path
> initially, all entries are Os
> mark to 1 when the position is visited
TE Wey errrA Mazing Problem
initialize @ stack to the maze’s entrance coordinates and direction to north;
while (stack is not empty) {
F* move to position at top of stack */
‘ = delete from top of the stack;
while (there are more moves from current position) {
= coordinates of next move;
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) {
mark{next_row][next_col] = 4;
add to the top of the stack;
row = next_row;
col = next_col;
dir = north;
}
}
printf(no path found
maze algorithm
PE Re Te Tee lle col CaA Mazing Problem
#define MAX_STACK_SIZE 100
typedef struct {
short int row;
short int col;
short int dir;
} element;
element stack[MAX_STACK_SIZE];
m Bound for the stack size
> the stack need have only as many positions as there are zeroes in
the maze
TE erent erm LyA Mazing Problem
—oee rors
DHororoHne
o-oHcHors
o-oncHors
SoH oHoHS
Our oeeeoe
simple maze with a long path
TE rey elec meayHT
Evaluation of
ExpressionsEvaluation of Expressions
g Introduction
| x = a/b-c+d*e-a*c
> to understand the meaning of expressions and statements,
* figure out the order in which the operations are performed
> operator precedence hierarchy
* determine the order to evaluate operators
> associativity
* how to evaluate operators with the same precedence
TE ero ela ranEvaluation of Expressions
token precedence | associativity
On. 17 left-to-right
++ 16 left-to-right
++ 1=-+ & * sizeof 15, right-to-left
| (type) 14 right-to-left
*/% 1B left-to-right
12 left-to-right
11 left-to-right
= 10 left-to-right
9 left-to-right _|
8 left-to-right
f. left-to-right
1 6 left-to-right
5 left-to-right
4 left-to-right
3 right-to-left
= Wa = Kaz >>= B= 2 right-to-left
: 1 left-to-right
precedence hierarchy for C language
TE Were a remo LdEvaluation of Expressions
m@ by human_being
1)assign to each operator a priority
2)use parenthesis and evaluate inner-most ones
(((a*(b+c))+(d/e))-(a/(c*d)))
m by compiler
> by reworking to postfix form
1) translation (infix to postfix)
2) evaluation (postfix)
infix form : operand (operator) operand
postfix form : operand operand (operator)
TE Ween erie)Evaluation of Expressions
infix postfix
243"4 234%
a*b+5 ab*5+
(1+2)*7 1 2+7*
able ab¥e/
((al(b-c+d))*(e-a)*c abe-d+/ea-*c*
alb-c+d*e-a*c ab/c-de*+ac*-
infix and postfix notation
@ evaluation of postfix expression
> scan left-to-right
> place the operands on a stack until an operator is found
> perform operations
TE ery eraseEvaluating Postfix Expression
6 2/3-4 2*+
stack
token | i) tH] py top
6 (6 0
2 |6 2 1
/ 6/2 0
3. Jorn 3 1
- — |6/2-3 0
4 |6/2-3 4 1
2 | 6/2-3 4 2 2
* | 6/2-3 42 1
+ |6/2-3+4+2 0
> postfix evaluation
TE ero ela ranEvaluating Postfix Expression
m@ get_token()
> used to obtain tokens from the expression string
m eval()
> if the token is an operand, convert it to number and push to
the stack
> otherwise
1) pop two operands from the stack
2) perform the specified operation
3) push the result back on the stack
TE ern el racianEvaluation of Expressions
#define MAX_STACK_SIZE 100 /* max stack size */
#define MAX_EXPR_SIZE 100
/* max expression size */
typedef enum {Iparen, rparen, plus, minus, times, divide,
mode, eos, operand
} precedence;
int stack[MAX_STACK_SIZE}; /* global stack */
char expr[MAX_EXPR_SIZE]; /* input string */
@ represent stack by a global array
>» accessed only through top
> assume only the binary operator +,-,*,/, and %
> assume single digit integer
TE ony elem)Evaluation of Expressions
m function to evaluate a postfix expression
int eval()
precedence token;
Char symbol;
int op1, op2;
int n= 0;
et_token(&symbol, &n);
7 != eos)
if Gone operand)
PUshietop, ‘symbol-’0’);
se3 = pop(&top);
Op1 = pop(&top);
‘switch (token)
Case plus: push(Stop, op1+0p2); break;
lop,
el
case minus: push(&top, op1-op4); break;
case times: push(&top, op1*op2); break;
case divide: push(&top, op1/op2); break;
case mod: push(&top, op1%op2);
loken = get_token(&symbol, &n);
return pop(&top);
Teun Perret erieEvaluation of Expressions
m function to get a token
precedence get_token(char “psymbol, int *pn)
{
*psymbol = expr[(*pn)++]:
switch (*psymbol)
case ‘(‘ : return Iparen;
case ‘)' : return rparen;
: return plus;
> return minus;
return times;
return divide;
case ‘%' : return mod;
case ‘': return eos;
default : return operand; /* no error checking */
}
}Evaluating Postfix Expression
= Complexity
>» time: O(n) where
n: number of symbols in expression
> space: stack expr[MAX_EXPR_SIZE]
TE Werte erm rdInfix to Postfix
m Algorithm for producing a postfix expression from an
infix one
1) fully parenthesize the expression
2) move all binary operators so that they replace their
corresponding right parentheses
3) delete all parentheses
> eg) a/b-c+d*e-a*c
*® ((((a/b)-c)+(d*e))-(a*c))
*® ab/c-de*+ac*-
> requires two passes
TE ery etreInfix to Postfix
m Form a postfix in one pass
> order of operands is the same in infix and postfix
> order of operators depends on precedence
> we can use a stack
m Ex 3.3 [simple expression]
> simple expression a+b*c
* yields abc*+ in postfix
* output operator with higher precedence before those with lower
precedence
TE ero errandInfix to Postfix
token (0) u aes pI top| output
a -lia
+ + 0 |a
b + 0 Jab
* + * 1 |ab
¢ + * 1 | abe
eos -1 | abe*+
> translation of a+b*c to postfix
TE eed elec meeInfix to Postfix
m Ex 3.4 [parenthesized expression]
> parentheses make the translation process more difficult
* equivalent postfix expression is parenthesis-free
> expression a*(b+c)*d
» yield abc+*d* in postfix
> right parenthesis
* pop operators from a stack until left parenthesis is reached
TE eo el racranInfix to Postfix
stack
[0] i} [2]
token
Ss
3
output
me
a
a
a
ab
ab
abe
abe+
abe+*
abe+*d
abe+*d*
Beene en ee
ee eee RH ROR
+
ecoocoonnero
2
&
> translation of a*(b+c)*d to postfix
TE ery el eacranInfix to Postfix (skip)
™ a precedence-based scheme for stacking and unstacking
operators
top —|
stack
compare token
in-stack precedence
> isp[stack{top]] < icp[token]
* push
> isp[stack{top]] = icp[token]
* pop and print
incoming precedence
TE roy ela ranInfix to Postfix (skip)
m Use two types of precedence (because of the ‘(‘ operator)
>» in-stack precedence(isp)
> incoming precedence(icp)
precedence stack[MAX_STACK_SIZE],
/* isp and icp arrays -- index is value of
precedence Iparen, rparen, plus, minus,
times, divide, mode, eos */
static int isp[] = {0,19,12,12,13,13,13,0};
static int icp{] = {20,19,12,12,13,13,13,0};
TE ony ermInfix to Postfix (skip)
void postfix(void)
char symbol;
precedence token;
intn = 0;
0s;
for token = get_token(&symbol, &n); token != eos: token = get_token(&symbol, &n) {
if (token == operand)
print’%c’, symbol):
elseif token == rparen) {
while (stack{top] |= lparen)
print token(pop(&top))
pop(&top);
unction to convert
from infix to posttfi:
alse {
while (ispfstack{top]] >= icp{token})
print_token(pop(&top)):
push(&top, token),
While (token = pop(&top)) != e0s)
print_token(token!
\ printf(n’);
TE evo mayInfix to Postfix (skip)
@ Postfix
> no parenthesis is needed
> no precedence is needed
@ Complexity
> time: O(r) where
* r: number of symbols in expression
» space: S(n) = n where
* n: number of operators
TE roy el racranWAH
Multiple Stacks and
Queues (skip)
=
COE oe teenMultiple Stacks and Queues (skip)
m multiple stacks
we need n stacks simultaneously
> maximum size of each stack is unpredictable
» size of each stack is dynamically varying
> efficient memory utilization for multiple stacks is difficult
TE roy etre ranMultiple Stacks and Queues (skip)
m@ sequential mappings of stacks into an array
> memory{MEM_SIZE]
m@ case n=2
> the first stack
* bottom element: memory{0]
* grows toward memory{MEM_SIZE-1]
» the second stack
* bottom element: memory[MEM_SIZE-1]
* grows toward memory{0]
TE ero el racranMultiple Stacks and Queues (skip)
m = MEM SIZE
0 12 m-1
memory
boundary[0] = -1 boundary[1] = m
top[0] = -1 top[1] =m
stack 1 stack 2
> top[0] =-1: stack 1 is empty
> top[1] = m: stack 2 is empty
TE Wont erie mer)Multiple Stacks and Queues (skip)
m case n23
> boundary
* point to the position immediately to the left of the bottom element
>» top
* point to the top element
#define MEM_SIZE 100
#define MAX_STACKS 10
element memory[MEM_ SIZE];
int top[MAX_STACKS];
int boundary[MAX_STACKS];
int n; /* number of stacks, n < MAX_STACKS */
TE ered ere mLMultiple Stacks and Queues (skip)
@ divide the array into roughly equal segments
top[0] = boundary[0] = -1;
for(i = 1;i initial configuration for n stacks in memory{m]
TE ‘Networking Laboratory 57/Multiple Stacks and Queues (skip)
a initially
> boundary[i] = top[i] = m/n* i-1
g i-th stack is empty
> - top[i] == boundary{i]
m /-th stack is full
> - top[i] == boundary[i+1]
TE erred rmMultiple Stacks and Queues (skip)
void push(int i, element item) {
/* add an item to the i-th stack */
if (top[i] == boundary[i+1])
stack_full(i);
memory[++top|i]] = item;
I
> push an item to the i-th stack
‘element pop(int i) {
/* remove top element from the i-th stack */
if (top[i] == boundaryfi])
return stack_empty(i);
return memory[top[i]--];
}
> pop an item from the i-th stack
Tne roy etre ranMultiple Stacks and Queues (skip)
m Ex) n=5, m = 20, push(1, x)
Bix 19
,& E @ ah. 11|12
Pe stn Te al
b[2]=7 b[3]=11 b[4]=15
t[4]=16
b[OJ=-1 b[1]=3
t([O]=-1 t[1]=7 st [2]=11 tt [3] =13
Werte md
TEMultiple Stacks and Queues (skip)
@ 1) find the least jfori such that there is a free space between stacks j and (j+1)
* ie.) tif] < bij+1]
* - move stack i+1, i+2, ---,j one position to the right creating a
space between stacks j and (i+1)
@ 2) if there is no such a j, then look up the left direction
> -data movement: O(m)
TE ererety ere md