Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
10 views

Lecture05 Updated

Uploaded by

Rana Haris
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Lecture05 Updated

Uploaded by

Rana Haris
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 35

1

Lecture #5
• Stacks
• Queues
2
Stacks
What’s the big picture?
A stack is a data structure that resembles
a stack of plates at a buffet.
Just like a stack of plates, the last
plate/value you add is at the top of the
stack, and thus the first to be removed.

10 8

10 8
10
Uses:
Use stacks to find
8 a path through a
10 10 maze, “undo” in a
word processor,
The last-added/first-removed aspect of and evaluate math
expressions.
stacks can help solve many hard problems!
4

The Stack: A Useful ADT


A stack is an ADT that holds a collection of items (like ints)
where the elements are always added to one end.

Just like a stack of plates, the last item pushed onto the
top of a stack is the first item to be removed.

Stack operations:
• put something on top of the stack (PUSH)
• remove the top item (POP)
• look at the top item, without removing it
• check to see if the stack is empty

We can have a stack of any type of variable we like:


ints, Squares, floats, strings, etc.
The Stack
5
Note: The stack is called
a Last-In-First-Out
data structure.
I can… Can you figure out why?
Push 5 on the stack.
last in first out
Push -3 on the stack.
Push 9 on the stack.
Pop the top of the stack. 4
9
Look at the stack’s top value. -3
Push 4 on the stack. 5
Pop the top of the stack
Pop the top of the stack
Look at the stack’s top value.
Pop the top of the stack

Note: You can only access the top item of the stack,
since the other items are covered.
6

Stacks
int main(void)
class Stack // stack of ints {
{ Stack is;
public:
Stack(); // c’tor is.push(10);
is.push(20);
void push(int i);
int pop(); ...
bool is_empty(void); }
int peek_top();
private:
... Answer:
}; How about an array
and a counter variable
to track where the
top of the stack is?
Question:
What type of data structure can we
use to implement our stack?
Implementing a Stack
7

To initialize our stack,


const int SIZE = 100; we’ll specify that the first
Let’s make sure we th never
class Stack item
Place our should
new go in in
value the 0
the
over-fill (overflow) our stack!
{
next slot
openofslot
theofarray.
the
public: Update For the this simple
location whereexample, let’s
Stack() { m_top = 0; }
our array…
next justm_top
item exit specifies
if this
should be happens.
void push(int val) {
placed where
in thethat is!
array.
if (m_top >= SIZE) exit(-1); // overflow!
m_stack[m_top] = val; Since m_top points to where our
m_top += 1;
We item
next can’twill
popbeanpushed…
item from
our stack if it’s empty!
} Extract the value it
Let’s decrement
Terminate from
our the top
toprogram!
point it to
int pop() {Let’s use an array of
whereto stack
the hold and return
the current it to is!
top item
if (m_top == 0) our stack
exit(-1); items. the user.
// underflow
m_top -= 1;
We’ll
This stack
return m_stack[m_top];
mayuse a simple
hold aint to
} maximum keep track
of 100 of where the
items.
...
private: next item should be
int m_stack[SIZE]; added to the stack.
int m_top;
};
Stacks
8

const int SIZE = 100;


The first item we push int main(void)
{
class Stack will be placed in Stack is;
{ Currently, our m_top m_stack[0].
points to the int a;
The
next second
open slot item
in the we
stack…
public: 1 10
>=>=100?
>= 100?
100?
push7 =will
10
5
m_stack[1]
m_stack[0]
m_stack[1]
Stack() { m_top 0; }be ==placed
10
7
5 in is.push(5);
But we
void push(int want
slot
val)#1to
{of return the top item
our stack. is.push(10);
already
if (m_top pushed
>= SIZE) on the stack.
exit(-1); // overflow a = is.pop();
m_stack[m_top] = val; cout << a;
m_top So
+= first
1; we must decrement our is.push(7);
} m_top variable…
2 == 0??
}

return
int pop() { m_stack[1] is
So we
if (m_top == return 10
0) exit(-1); // underflow m_top 2
0
1
m_top -= 1;
return m_stack[m_top]; m_stack
} 0 5
...
1 7
10
2
private: ... …
int m_stack[SIZE];
10
7 99
int m_top; 5 a
}; 10
Stacks
9

Always Remember:
const int SIZE = 100; When we push, we:
class Stack
{ A. Store the new item in m_stack[m_top]
public: B. Post-increment our m_top variable
Stack() { m_top = 0; } (post means we do the increment after storing)
void push(int val) {
if (m_top >= SIZE) exit(-1); // overflow
m_stack[m_top] = val;
m_top += 1;
}

int pop() {
if (m_top == 0) exit(-1); // underflow
m_top -= 1;
return m_stack[m_top]; Always Remember:
}
When we pop, we:
... A. Pre-decrement our m_top variable
private: B. Return the item in m_stack[m_top]
int m_stack[SIZE]; (pre means we do the
int m_top; decrement before returning)
};
Stacks
10

And as with cin and cout, you can


Here’s the syntax to define a stack:
remove the std:: prefix if you add a
Stacks are so popular that the C++ people
using actually
namespace std; wrote
std::stack<type> variableName;
one for you. It’s in the Standard Template Library (STL)!
command!
For example:
#include <iostream>
#include <stack> // required!
std::stack<string> stackOfStrings;
using namespace std; std::stack<double> stackOfDoubles;
int main()
{
stack<int> istack; // stack of ints
std::stack<int>
So to get the top item’s value, before
istack.push(10); // addpopping
item toit, use
top the top() method!
istack.push(20);

cout << istack.top(); // get top value


istack.pop(); // kill top value
Note: The STL pop() command
simply throws away the top item
if (istack.empty() == false)
cout << istack.size(); from the stack…
} but it doesn’t return it.
11

Stack Challenge
Show the resulting stack after the following program runs:

#include <iostream>
#include <stack>
using namespace std;

int main()
{
stack<int> istack; // stack of ints

istack.push(6);
for (int i=0;i<2;i++)
{
int n = istack.top();
istack.pop();
istack.push(i);
istack.push(n*2);
}
}
12

Stack Challenge
Show the resulting stack after the following program runs:

#include <iostream>
#include <stack>
using namespace std;

int main()
{ i 0
1
stack<int> istack; // stack of ints
n
istack.push(6);
for (int i=0;i<2;i++) 24
{ 12
1
int n = istack.top();
6
0
istack.pop();
istack.push(i);
istack.push(n*2);
}
}
13

Common Uses for Stacks


Stacks are one of the most USEFUL data structures
in Computer Science.

They can be used for:


• Storing undo items for your word processor
The last item you typed is the first to be undone!
• Evaluating mathematical expressions
5 + 6 * 3  23
• Converting from infix expressions to postfix
expressions
A+BAB+
• Solving mazes

In fact – they’re so fundamental to CS that they’re


built into EVERY SINGLE CPU in existence!
14

A Stack… in your CPU!


Did you know that every CPU has a built-in stack used
to hold local variables and function parameters?
When you pass a value to a
void bar(int b) function, the CPU pushes
{ that value
When onto
you pass a stack
a value to ainfunction,
cout << b << endl; thethe
CPUcomputer’s memory.
pushes that value onto a stack
} in the computer’s memory.
void foo(int a) When a function returns,
{ its …
variables
when and
your function returns, the values
Local variables
cout << a << endl; parameters are
areare popped
popped offoff
the stack and go away.
10 stored on the
bar(a*2); the stack and go away.
} computer’s built-in
Output: b
stack! 10
int main(void) Every a a local
5 time you declare 5 variable,
{ program pushesxit on the PC’s stack
your10
int x = 5; automatically!
5
foo( 5
x );
}
Undo!
15

When the user hits the


So undo
how does the UNDO
button…
feature of your favorite
so cool
Carey is not
word processor work?
The word processor
pops the top item off
the stackaand
It uses removes
stack, of course!
it from the document!
Every time you type a new
word, it’s added to the stack!

Every time you cut-and-paste “so”  “not”


an image into way,
In this your the
doc,word
it’s img5.jpg
“cool”
added tocan
processor thetrack
stack!
the last X “so”
things that you did and
And even when you delete “is”
properly undo them!
text or pictures, this is “Carey”
tracked on a stack! undo stack
16

Postfix Expression Evaluation


Most people are used to infix notation, where the
operator is in-between the two operands, e.g.: A + B

As we’ll
Postfix notation is another waysee, postfix
to write expressions
algebraic have–
expressions
here the operator follows
no the
suchoperands: AB+
ambiguity!

Infix Postfix
Here are some infix 15 + 6 15 6 +
If you’ve ever
expressions andused an9 HP
– 4 Is that9 (5+10)
4 - *3
calculator, you’ve used
their postfix
(15 + 6) * 5 15or
6 + 5 *
equivalents:
postfix notation!
7 * 6 + 5 5 +7(10
6 ** 53)+
To3 understand
+ (4 * 5) infix
3 4 5expressions,
* + the
computer has to be equipped with
Postfix expressions are easier forprecedence
a computer torules!
compute than
infix expressions, because they’re unambiguous.

Ambiguous infix expression example: 5 + 10 * 3


17

Postfix Evaluation Algorithm


Inputs: postfix expression string
Output: number representing answer 7 6 * 5 +
Private data: a stack
1. Start with the left-most token. v1v1==42
7 v2 v2==65
2. If the token is a number: temp =
temp =67*6 = =42
542+5 47
a. Push it onto the stack 42
47
7
3. Else if the token is an operator:
a.… //
Popwe’ll
thesee
topthis
valueininto a variable called v2, and
a bit!
the second-to-top value into v1.
b. Apply operator to v1 and v2 (e.g., v1 / v2)
c. Push the result of the operation on the stack
4. If there are more tokens, advance to the next
token and go back to step #2
5. After all tokens have been processed, the top #
on the stack is the answer!
18

Class Challenge
Given the following postfix expression: 6 8 2 / 3 * -
Show the contents of the stack *after* the 3 has been
processed by our postfix evaluation algorithm.
Reminder:
1. Start with the left-most token.
2. If the token is a number:
a. Push it onto the stack
3. If the token is an operator:
a. Pop the top value into a variable called v2, and the
second-to-top value into v1.
b. Apply operator to the two #s (e.g., v1 / v2)
c. Push the result of the operation on the stack
4. If there are more tokens, advance to the next token and go
back to step #2
5. After all tokens have been processed, the top # on the stack
is the answer!
19

Infix to Postfix Conversion


Since people are more
Stacks can also be used to convert infix expressions to
used to infix notation…
postfix expressions:
You can let the user
For example,
type in an infix
expression…
From: (3 + 5) * (4 + 3 / 2) – 5
To: 3 5 + 4 3 2 / + * 5 –
And then convert it into
a postfix expression.
Or
Finally, you can use the
From: 3 + 6 * 7 * 8 – 3
postfix evaluation alg
To: 3 6 7 * 8 * + 3 - (that we just learned)
to compute the value of
the expression.
20

Infix to Postfix Conversion


Inputs: Infix string
Output: postfix string (initially empty)
Private data: a stack
1. Begin at left-most Infix token.
2. If it’s a #, append it to end of postfix string followed by a space
3. If its a “(“, push it onto the stack.
4. If it’s an operator and the stack is empty:
a. Push the operator on the stack.
5. If it’s an operator and the stack is NOT empty:
a. Pop all operators with greater or equal precedence off the

stack and append them on the postfix string.


b. Stop when you reach an operator with lower precedence or a (.
c. Push the new operator on the stack.
6. If you encounter a “)”, pop operators off the stack and append
them onto the postfix string until you pop a matching “(“.
7. Advance to next token and GOTO #2
8. When all infix tokens are gone, pop each operator and append it }
21

Solving a Maze with a Stack!


We can also use a stack to determine if a maze is
solvable:

0 1 2 3 4 5 6 7
Start 0
(1,1) 1
2
3
4 Finish
5 (6,6)
6 X
7
22

Solving a Maze with a Stack!


Inputs: 10x10 Maze in a 2D array,
Starting point (sx,sy)
Ending point (ex,ey)
Output: TRUE if the maze can be solved, FALSE otherwise
Private data: a stack of points

class Point class Stack


{ {
public: public:
Point(int x, int y); Stack(); // c’tor
int getx() const; void push(Point &p);
int gety() const; Point pop();
private: ...
int m_x, m_y; private:
}; ...
};
Solving a Maze with a Stack
28

Depth-first Search Visualization

0 1 2 3 4 5 6 7 Watch how our search goes


0 “deep” in the same direction
1
start # # ### # until it hits a dead end…

2 # # # It does this because it always


processes the last item
3 # ## # pushed on the stack…
4 # Which happens to be right
5 ## next to the current square
being processed.
6 # goal
7 This is why it’s called a
“depth-first” search.
Queues
What’s the big picture?
A queue is a super-useful* data structure
that resembles a conveyer belt of dishes.
Dishes are added to the rear of the queue...
rear front rear front
10
14 8 10 14 8

and dishes are extracted from its front...


rear front rear front Uses:
Use queues for
10 14 8 10 14 vehicle navigation,
implementing
twitter feeds,
The first-in/first-out property of queues is opposite queueing songs on
of the last-in-first-out property of stacks. Spotify, etc.
31

Another ADT: The Queue


The queue is another ADT that is just a like a line at
the store or at the bank.

The first person in line is the first person out of line


and served.
This is called a FIFO data structure:
FIRST IN, FIRST OUT.

Every queue has a front rear front


and a rear. You enqueue 17
4 -3 5
4 –3
17
items at the rear and
dequeue from the front.

What data structures could you use to implement a queue?


32

The Queue Interface


void enqueue(int a):
Inserts an item on the rear of the queue
int dequeue():
Removes and returns the top item from the front
of the queue
bool isEmpty():
Determines if the queue is empty
int size():
Like a Stack, we
Determines the # of items in the queue
can have queues
int getFront(): of any type of
Gives the value of the top item on the queue
data! Queues of
without removing it like dequeue strings, Points,
Nerds, ints, etc!
33

Common Uses for Queues


Often, data flows from the Internet faster than the
computer can use it. We use a queue to hold the data
until the browser is ready to display it...

Every time your computer receives a character, it


enqueues it:
internetQueue.enqueue(c);

Every time your Internet browser is ready to get


and display new data, it looks in the queue:
while (internetQueue.isEmpty() == false)
{
char ch = internetQueue.dequeue();

cout << ch; // display web page…


}
34

Common Uses for Queues


You can also use queues to search through mazes!

If you use a queue instead of a stack in our searching


algorithm, it will search the maze in a different order…

Instead of always exploring the last x,y location pushed


on top of the stack first…

The new algorithm explores the oldest x,y location


inserted into the queue first.
Solving a Maze with a Queue
36

Breadth-first Search Visualization


Watch how the squares we
0 1 2 3 4 5 6 7 explore expand out like
0 ripples in a pond…

1
start ## ## # # It does this because each new
square to explore is added to
2 # # # the END of the queue…
3 # ## # So squares closer to the
4 # starting square are explored
5 # ## before squares further away.

6 # goal
7 This is why it’s called a
“breadth-first” search.
37

Queue Implementations
We can use an array and an integer to represent a queue:

int queue[6], rear = 0;

queue 6
5 6
9 9 rear 02
3
1
0 1 2 3 4 5 0
• Every time you insert an item, place it in the rear slot
of
the array
• Every time and
you increment
dequeue anthe rear
item, count
move all of the items
forward in the array and decrement the rear count.

What’s the problem with the array-based implementation?


If we have N items in the queue, what is the cost of:
(1) inserting a new item, (2) dequeuing an item
38

Queue Implementations
We can also use a linked list to represent a queue:

• Every time you insert an item, add a new node to the


end
of thetime
• Every linked
youlist.
dequeue an item, take it from the head
of the linked list and then delete the head node.

Of course, you’ll want to make sure you have


both head and tail pointers…

or your linked-list based queue will be really


inefficient!
39

The Circular Queue


The circular queue is a clever type of
array-based queue.

Unlike our previous array-based


queue, we never need to shift items
with the circular queue!

queue
X
6
5
0
6
9
1
9
2 3 4 5

Let’s see how it works!


40

The Circular QueueIf the


H count is zero, then you
know the queue is empty. If the
count
T is N, you know it’s full…
Private data:
an array: arr 0 1 2 3 4 5
an integer: head
an integer: tail 6
42 4 -1 9 7 5
an integer: count
0
5
4
12 head 310
2
6 4 -1 tail 31
0
• To initialize your queue, set: count 50
2
4
31 Enqueue: 6
count = head = tail = 0 Enqueue: 4
• To insert a new item, place it in arr[tail] Enqueue: -1
Dequeue -> 6
and then increment the tail & count values
Enqueue: 9
• To dequeue the head item, fetch arr[head] Enqueue: 7
and increment head and decrement count Dequeue -> 4
Enqueue: 5
• If the head or tail go past the end of
Enqueue: 42
the array, set it back to 0. Dequeue -> -1
42

A Queue in the STL!


The people who wrote the Standard Template
Library also built a queue class for you:

#include <iostream>
#include <queue>

int main()
{
std::queue<int> iqueue; // queue of ints

iqueue.push(10); // add item to rear


iqueue.push(20);
cout << iqueue.front(); // view front item
iqueue.pop(); // discard front item
if (iqueue.empty() == false)
cout << iqueue.size();
}
43

Class Challenge
Given a circular queue of 6 elements, show the
queue’s contents, and the Head and Tail pointers
after the following operations are complete:

enqueue(5)
enqueue(10)
enqueue(12)
dequeue()
enqueue(7)
dequeue()
enqueue(9)
enqueue(12)
enqueue(13)
dequeue()

You might also like