1 stacks and queues reading: sections 3.6 and 3.7

Post on 14-Dec-2015

224 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1

Stacks and Queues

Reading: Sections 3.6 and 3.7

2

Stack ADT - LIFO

• Collections: – Elements of some proper type T

• Operations: – Feature: Last In, First Out– void push(T t)– void pop()– T top()– bool empty()– unsigned int size()– constructor and destructor

3

Stack Model—LIFO

• Empty stack S– S.empty() is true– S.top() not defined– S.size() == 0

food chain stack

4

Stack Model—LIFO

• S.push(“mosquito”)– S.empty() is false– S.top() == “mosquito”– S.size() == 1

mosquito

food chain stack

5

Stack Model—LIFO

• S.push(“fish”)– S.empty() is false– S.top() == “fish”– S.size() == 2

fish

mosquito

food chain stack

6

Stack Model—LIFO

• S.push(“raccoon”)– S.empty() is false– S.top() == “raccoon”– S.size() == 3

raccoon

fish

mosquito

food chain stack

7

Stack Model—LIFO

• S.pop()– S.empty() is false– S.top() == “fish”– S.size() == 2

fish

mosquito

food chain stack

8

Implementations and Uses of Stack ADT

• Implementations – Any list implementation– list and vector C++ STL– Vector/List ADTs

• push_front()/pop_front()• push_back()/pop_back()

• Uses– Depth first search / backtracking– Evaluating postfix expressions– Converting infix to postfix– Function calls (runtime stack)– Recursion

9

Depth First Search—Backtracking

• Problem– Discover a path from start to goal

• Solution– Start from

• Node start– Stop

• If node is goal– Go deep

• If there is an unvisited neighbor, go there

– Backtrack• Retreat along the path to find

an unvisited neighbor, if cannot go deeper

• Outcome– If there is a path from start to goal, DFS finds one such path

1

2 3 4

5 6 87

9 10 1211

start

goal

10

Depth First Search—Backtracking (2)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

1Push

11

Depth First Search—Backtracking (3)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

2

1Push

Push

12

Depth First Search—Backtracking (4)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

5

2

1Push

Push

Push

13

Depth First Search—Backtracking (5)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

6

5

2

1Push

Push

Push

Push

14

Depth First Search—Backtracking (6)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

9

6

5

2

1Push

Push

Push

Push

Push

15

Depth First Search—Backtracking (7)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

6

5

2

1Push

Push

Push

Push

Pop

16

Depth First Search—Backtracking (8)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

5

2

1Push

Push

Push

Pop

17

Depth First Search—Backtracking (9)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

2

1Push

Push

Pop

18

Depth First Search—Backtracking (10)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal1Push

Pop

19

Depth First Search—Backtracking (11)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

3

1Push

Push

20

Depth First Search—Backtracking (12)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

7

3

1Push

Push

Push

21

Depth First Search—Backtracking (13)

• Stack

1

2 3 4

5 6 87

9 10 1211

start

goal

10

7

3

1Push

Push

Push

Push

22

DFS Implementation

DFS() {stack<location> S;

// mark the start location as visitedS.push(start);

while (!S.empty()) {t = S.top();if (t == goal) Success(S);if (// t has unvisited neighbors) {

// choose an unvisited neighbor n// mark n visited;S.push(n);

} else {BackTrack(S);

}}Failure(S);

}

23

DFS Implementation (2)

BackTrack(S) {while (!S.empty() && S.top() has no unvisited neighbors) {

S.pop();}

}

Success(S) {// print successwhile (!S.empty()) {

output(S.top());S.pop();

}}

Failure(S) {// print failurewhile (!S.empty()) {

S.pop();}

}

24

Evaluating Postfix Expressions

• Infix expression– Operators in middle of operands– 25 + x*(y – 5)

• Postfix expressions– operands precede operator– Z = 25 x y 5 - * +

• Tokens: atomics of expressions, either operator or operand• Example:

– 25 + x*(y – 5)– Tokens: 25, +, x, *, (, y, -, 5, )

25

Evaluating Postfix Expressions (2)

• Evaluation algorithm:– Use stack of tokens– Repeat

• If operand, push onto stack• If operator

– pop operands off the stack– evaluate operator on operands– push result onto stack

• Until expression is read• Return top of stack

• Most CPUs have hardware support for this algorithm• Translation from infix to postfix also uses a stack

(software)

26

Evaluating Postfix Expressions (3)

• Original expression: – 1 + (2 + 3) * 4 + 5

• Evaluate: – 1 2 3 + 4 * + 5 +

27

Evaluating Postfix Expressions (4)

• Input: 1 2 3 + 4 * + 5 +• Push(1)

1

28

Evaluating Postfix Expressions (5)

• Input: 2 3 + 4 * + 5 +• Push(2)

2

1

29

Evaluating Postfix Expressions (6)

• Input: 3 + 4 * + 5 +• Push(3)

3

2

1

30

Evaluating Postfix Expressions (7)

• Input: + 4 * + 5 +• Pop() == 3• Pop() == 2

1

31

Evaluating Postfix Expressions (8)

• Input: + 4 * + 5 +• Push(2 + 3)

5

1

32

Evaluating Postfix Expressions (9)

• Input: 4 * + 5 +• Push(4)

4

5

1

33

Evaluating Postfix Expressions (10)

• Input: * + 5 +• Pop() == 4• Pop() == 5

1

34

Evaluating Postfix Expressions (11)

• Input: * + 5 +• Push(5 * 4)

20

1

35

Evaluating Postfix Expressions (12)

• Input: + 5 +• Pop() == 20• Pop() == 1

36

Evaluating Postfix Expressions (13)

• Input: + 5 +• Push(1 + 20)

21

37

Evaluating Postfix Expressions (14)

• Input: 5 +• Push(5)

5

21

38

Evaluating Postfix Expressions (15)

• Input: +• Pop() == 21• Pop() == 5

39

Evaluating Postfix Expressions (16)

• Input: +• Push(21 + 5)

26

40

Evaluating Postfix Expressions (17)

• Input: • Pop() == 26

41

Postfix Evaluation Implementation

Evaluate(postfix expression) {

// use stack of tokens;while(// expression is not empty) {

t = next token;if (t is operand) {

// push onto stack} else {

// pop operands for t off stack// evaluate t on these operands// push result onto stack

}}// return top of stack

}

42

Infix to Postfix Conversion• Depends on operator precedence and associativity• We present a limited version

– +, -, *, /, (, )– Assuming usual precedence and associativity

• High level idea– If input token is an operand, output directly– If input token is an operator, we need to compare the precedence of

this operator with other neighboring operators, output the one with highest precedence

– Parentheses need to handle differently• ( has highest precedence when encountered in input compared to operators in

stack, so we always push a (• ) is used to pop everything till ( in stack

43

Example

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b+

44

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c+

*

45

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c * + +

46

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c * + d +

(

47

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c * + d e +

(

*

48

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c * + d e * f+

(

+

49

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c * + d e * f ++

50

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c * + d e * f + g+

*

51

Example (cont’d)

• Infix:– a + b * c + ( d * e + f ) * g

• Postfix– a b c * + d e * f + g * +

a + b * c + ( d * e + f ) * g

a b c * + d e * f + g * +

Infix to Postfix Conversion

52

void infix2postfix(const vector<token> &infix) { stack<token> s; for (I = 0; I < infix.size(); ++I) { if (infix[I] is operand)

print infix[I]; else if (infix[I] is +, -, *, /, or ( ) { while (s.top() != ‘(‘ && s.top().precedence >= infix[I].precedence) {

print s.top(); s.pop(); } s.push(infix[I]); } else if (infix[I] == ) ) {

while (s.top() != ( ) { print s.top(); s.pop();}

s.pop(); // remove ( } } while (!s.empty()) { print s.top(); s.pop(); }}

53

Runtime Stack

• Runtime environment– Static

• Executable code• Global variables

– Stack• Push for each function call• Pop for each function return• Local variables

– Heap• Dynamically allocated memories • new and delete

static

stack

heap

program memory

54

Recursion

• Order 1: function calls itself• Order 2: f() calls g(), and g() calls f()• Facilitated by stack

55

Reading Exercise

• How to use stack to– To check if brackets are balance? (Section 3.6.3)

56

Queue ADT - FIFO

• Collection– Elements of some proper type T

• Operations– Feature: First In, First Out– void push(T t)– void pop()– T front()– bool empty()– unsigned int size()– Constructors and destructors

57

Queue Model—FIFO

• Empty Q

animal parade queue

58

Queue Model—FIFO

• Q.Push(“ant”)

ant

front

back

animal parade queue

59

Queue Model—FIFO

• Q.Push(“bee”)

ant bee

front

back

animal parade queue

60

Queue Model—FIFO

• Q.Push(“cat”)

ant bee cat

front

back

animal parade queue

61

Queue Model—FIFO

• Q.Push(“dog”)

ant bee cat dog

front

back

animal parade queue

62

Queue Model—FIFO

• Q.Pop()

bee cat dog

front

back

animal parade queue

63

Queue Model—FIFO

• Q.Pop()

cat dog

front

back

animal parade queue

64

Queue Model—FIFO

• Q.Push(“eel”)• Q.Pop()• Q.Pop()

eel

front

back

animal parade queue

65

Implementations and Uses of Queue ADT

• Implementations– Any list implementation

• push_front()/pop_back()• push_back()/pop_front()

• Uses– Buffers– Breadth first search– Simulations– Producer-Consumer Problems

66

Breadth First Search

• Problem– Find a shortest path from start to goal

• Solution– Start from

• Node start– Visit

• All neighbors of the node– Stop

• If a neighbor is goal– Otherwise

• Visit neighbors two hops away

– Repeat (Stop/Otherwise)• Visiting neighbors N hops

away

1

2 3 4

5 6 87

9 10 1211

start

goal

67

Breadth First Search (2)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

1

Push

68

Breadth First Search (3)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

Pop

69

Breadth First Search (4)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

2 3 4

Push Push Push

70

Breadth First Search (5)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

Pop

3 4

71

Breadth First Search (6)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

3 4 5 6

Push Push

72

Breadth First Search (7)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

4 5 6

Pop

73

Breadth First Search (8)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

4 5 6 7 8

Push Push

74

Breadth First Search (9)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

5 6 7 8

Pop

75

Breadth First Search (10)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

6 7 8

Pop

76

Breadth First Search (11)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

7 8

Pop

77

Breadth First Search (12)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

7 8 9

Push

78

Breadth First Search (13)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

8 9

Pop

79

Breadth First Search (14)

• Queue

1

2 3 4

5 6 87

9 10 1211

start

goal

8 9 10

Push

80

BFS Implementation

BFS {queue<location> Q;

// mark the start location as visitedQ.push(start);while (Q is not empty) {

t = Q.front();for (// each unvisited neighbor n of node t) {

Q.push(n);if (n == goal) Success(S);

}Q.pop();

}Failure(Q);

}

81

Adaptor Class

• Adapts the public interface of another class• Adaptee: the class being used• Adaptor: the new class being defined

– Uses protected object of the adaptee type– Uses the adaptee’s methods to define adaptor methods

• Stack and Queue implemented via adaptor classes

82

Stack Adaptor Requirements

• Stack– push()– pop()– top()– empty()– size()

• Can use List, Deque– Push(): push_back()– Pop(): pop_back()

83

Class Stacktemplate <typename T, class Container>class Stack {

protected:Container c;

public:void push(const T & x) { c.push_back(x); }void pop() { c.pop_back(); }T top() const { return c.back(); }int empty() const { return c.empty(); }unsigned int size() const { return c.size(); }void clear() { c.clear(); }

};

• Declaration– Stack<float, List<float> > floatStack;– Stack<int, Vector<int> > intStack;

• For STL stack container– template <typename T, typename Container = deque<T> > class stack;– stack<char> charStack;

84

Queue Adaptor Requirements

• Queue– push()– pop ()– front()– empty()– size()

• Can use List, Deque– Push(): push_back()– Pop(): pop_front()

85

Class Queuetemplate <typename T, class Container>class Queue {

protected:Container c;

public:void push(const T & x) { c.push_back(x); }void pop() { c.pop_front(); }T front() const { return c.front(); }int empty() const { return c.empty(); }unsigned int size() const { return c.size(); }void clear() { c.clear(); }

};

• DeclarationQueue<float, List<float> > floatQueue;Queue<int, List<int> > intQueue;

• For STL stack containertemplate <typename T, typename Container = deque<T> > class queue;queue<char> charQueue;

86

Reading assignment

• Double-end queues– Section 3.7.2

• A problem to consider– A palindrome is a sequence of characters that can be same

way forward and backward. – Can you think of a recursive algorithm to determine if an

input string (line) is a palindrome or not. Character case is ignored (that is, low-case and upper-case characters are considered the same). The new line character is not part of the input string.

top related