Lecture 3-2022

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 67

Chapter 3

Stacks & Queues


•Templates in C++
•The Stack ADT
•The Queue ADT
•SubTypeing & Inheritance in C++
•A Mazing Problem
•Evaluation of Expressions
•Multiple Stacks & Queues

2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 1


Template used in Selection Sort
1. Template <class KeyType>
2. void sort(KeyType *a, int n)
3. // sort the n KeyTypes a[0] to a[n-1] into nondecreasing order
4. {
5. for (int i=0;i<n;i++)
6. {
7. int j=i;
8. // find smallest KeyType in a[i] to a[n-1] // practical examples
9. for (int k=i+1;k<n;k++) float farray[100];
10. if (a[k]<a[j]) { j = k; } int intarray[200];
11. // interchange Rectangle r[10];
12. KeyType temp=a[i]; a[i]=a[j]; a[j]=temp;
13. } ………..
14. } sort(r,10);
sort(farray, 100);
sort(intarray, 200);

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 2
Copy Constructor
• The Copy Constructor
– is a special constructor that takes as its argument a
reference to an object of the same class and creates a
new object that is a copy.
• Shallow Copy
– By default, the compiler provides a copy constructor
that performs a member-by-member copy from the
original object to the one being created. This is called a
member wise or shallow copy.
• In many cases a shallow copy is not satisfactory.
– Here is a simple program with a bare bones version of
the Employee class.

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 3
Copy Constructor (example)
#include <iostream>
using namespace std; int main()
{
class Employee { Employee programmer("John",22);
public:
Employee(char *name, int id); cout << programmer.getName() << endl;
~Employee(); return 0;
char *getName(){ return _name; } }
//other accessor methods
private:
int _id;
char * _name;
};

Employee::Employee(char *name, int id)


Comments:
{ • Employee name is now stored in a
_id = id; dynamically allocated character array. It is
_name = new char[strlen(name) + 1]; of "string length + 1" to allow for the null
// allocates an character array object
strcpy(_name, name); terminator used with C-style strings, '\0'.
} • The strcpy function automatically adds the
Employee::~Employee() null terminator to the destination string.
{ • Also, notice that the destructor frees the
delete [ ] _name;
} memory used to hold the employee name.
This is needed to avoid a memory leak,
2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 4
Copy Constructor (example)
int main() {
Employee programmer(“John”, 22); • Let’s key in the
cout << programmer.getName() << endl; example and run it
//Lots of code .... • anything wrong?
Employee manager = programmer;
//Creates a new Employee "manager",
//which is an exact copy of the
//Employee "programmer".

return 0;
}
◼ It contains a serious bug and may die with an exception when run. The
problem is that the default member-wise copy constructor is being used to
create the "manager" object. But the member-wise copy copies the address
stored in the pointer _name in "programmer" to the pointer _name in
"manager".
◼ When you run the above program, programmer's destructor gets called first. It
works fine and frees the block in memory. When manager's destructor is
called, an exception is thrown when the delete is attempted because that
block of memory has already been released.
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 5
Copy Constructor (example)
class Employee { Employee::~Employee() {
public: delete[ ] _name;
Employee(char *name, int id);
Employee(Employee &rhs); }
~Employee();
char *getName(){return _name;} Employee::Employee( Employee &rhs)
int getId() {return _id;}
//other accessor methods {
private: _id = rhs.getId();
int _id; _name = new char[strlen(rhs.getName()) + 1];
char *_name; strcpy(_name, rhs._name);
};
}
Employee::Employee( char *name, int id)
{
_id = id;

_name = new char[strlen(name) + 1];

//allocates an character array object


strcpy(_name, name);
}

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 6
Template
• The Template (or parameterized type)
– can be viewed as a variable that can be instantiated to any data
type (fundamental or user-defined type)
– Template function in C++ makes it easier to reuse classes and
functions.
• Copy Constructor
– Is a special constructor which is invoked when an object is
initialized with another object
– Ex. Keytype temp=a[k] bool operator<(const rect& r1) const {
return nArea < r1.nArea;
• Example }

– Can we use the sort template for the Rectangle class?


– Well, not directly. We’ll need to use operator overloading to
implement “>” for Rectangle class.

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 7
Using Templates to Represent
Container Classes
• Container class
– a class that represents a data structure that contains or
stores a number of objects.
• Objects can be pushed/deleted from a container
class
– Array
– Bag
• Multiple occurrences of the same element
• Do not care about the position of an element
• Do not care which element is removed

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 8
Using Templates to Represent
Container Classes (Cont.)
class Bag
{
public:
Bag(int MaxSize=DefaultSize);
~Bag(); •Bag can only be used to store
void Push(int); //insert an integer into bag integers.
int Delete(int&); //delete an integer from bag
Boolean IsFull; •We would like to implement Bag
Boolean IsEmpty(); using templates so that it can be
private: used to store objects of any data
void Full(); //action when bag is full type.
void Empty(); //action when bag is empty
int *array; •See Prog. 3.5~3.6.
int MaxSize; //size of array
int top; //highest position in array that
contains an element
};

2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 9


Implement Container Class with
Template
1. Prefix the class definition
• of Bag & the definitions of all its member function
with the statement: template<class Type>

2. int is replaced by Type when it refers to an


object being stored in Bag

3. In all member functions headers


• The instance of “Bag” that associates the function
with class Bag is followed by <Type>

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 10
template <class Type>
Bag<Type>::Bag(int MaxBagSize):MaxSize(MaxBagSize) { Prog. 3.6
array=new Type[MaxSize];
top=-1;
} Use constant reference (&x):
1. Type may represent large object, considerable
template <class Type> overhead may be incurred if it is passed by value
Bag <Type>::~Bag(){
delete[ ]array; 2. It’s assumed that Type were not int & or → int &&
}
template <class Type>
void Bag<Type>::Push(const Type&x){
if(isFull()) Full();
else array[++top]=x;
}
template <class Type>
Type* Bag<Type>::Delete(Type&x){
if(IsEmpty()) {Empty(); return 0;}
int deletePos = top /2;
x=array[deletePos];
for(int index=deletePos; index<top; index++)
array[index]=array[index+1]; // compact upper half of array
top--;
return &x;
}

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 11
Stack
• A stack
– is an ordered list in which insertions and deletions are
made at one end called the top. It is also called a Last-
In-First-Out (LIFO) list.
– Given a stack S = (a0, …, an-1), a0 is the bottom element,
an-1 is the top element, and ai is on top of element ai-1, 0
< i < n.
a3
a3

a2 a2
a1 a1
a0 a0

Push (Push) Pop (Delete)


J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 12
Example: System Stack

Previous frame fp
pointer

Return Pushress
a1

Local variables
Previous frame pointer fp
Return Pushress main Previous frame
pointer
Return Pushress main
• Used by a program at run time to process function calls
– The previous frame pointer points to the stack frame of the invoking function
– The return Pushress contains the location of the statement to be executed after the
function terminates
• When the invoked function terminates, its stack frame is removed and the invoking
function continues its processing
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 13
Stack operations

E top
top D top
D D
C top C C
C
B top B B B
B
A top A A A A
A

Push Push Push Push del

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 14
ADT 3.1 Abstract Data Type Stack
template <class KeyType>
class Stack
{ // objects: A finite ordered list with zero or more elements

public:

Stack (int MaxStackSize = DefaultSize);


// Create an empty stack whose maximum size is MaxStackSize
Boolean IsFull();
// if number of elements in the stack is equal to the maximum size
// of the stack, return TRUE(1) else return FALSE(0)

void Push(const KeyType& item);


// if IsFull(), then StackFull(); else insert item into the top of the stack.

Boolean IsEmpty();
// if number of elements in the stack is 0, return TRUE(1) else return FALSE(0)

KeyType* Delete(KeyType& );
// if IsEmpty(), then StackEmpty() and return 0;
// else remove and return a pointer to the top element of the stack.
};
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 15
Implementation of Stack by Array

an-1

a2
a1
a0

a0 a1 a2 an-1
Array index 0 1 2 3 n-1

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 16
Queue
• A queue
– is an ordered list in which all insertions take place at one end and
all deletions take place at the opposite end.
– It is also known as First-In-First-Out (FIFO) lists.
• Manipulation Issue
– It’s intuitive to use array for implementing a queue. However,
queue manipulations (Push and/or delete) will require elements in
the array to move. In the worse case, the complexity is of
O(MaxSize).

a0 a1 a2 an-1

front rear

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 17
Shifting Elements in Queue

front rear

front rear

front rear
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 18
The Queue ADT
• Queue: an ordered list
– All insertions take place at one end
– All deletions take pace at the opposite end
– First-In-First-Out, FIFO
• Example
– Given a queue Q={a0,a1,…,an-1}
– a0 is the front element, an-1 is the rear element
– ai is behind ai-1 for 1 i n

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 19
ADT 3.2 Abstract Data Type Queue
template <class KeyType>
class Queue
{
// objects: A finite ordered list with zero or more elements
public:
Queue(int MaxQueueSize = DefaultSize);
// Create an empty queue whose maximum size is MaxQueueSize

Boolean IsFull();
// if number of elements in the queue is equal to the maximum size of
// the queue, return TRUE(1); otherwise, return FALSE(0)

void Push(const KeyType& item);


// if IsFull(), then QueueFull(); else insert item at rear of the queue

Boolean IsEmpty();
// if number of elements in the queue is equal to 0, return TRUE(1)
// else return FALSE(0)

KeyType* Delete(KeyType&);
// if IsEmpty(), then QueueEmpty() and return 0;
// else remove the item at the front of the queue and return a pointer to it
};
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 20
Class Queue & Its Operations
template<KeyType>
class Queue{
public:…
private:
int front; // front: index of the first element to be retrieved
int rear; // rear:index of the last element
KeyType *queue; // KeyType array
int MaxSize;
}

A A B A B C A B C D A B C D E B C D E
          

f,r f r f r f r f r f r

Push Push Push Push delete

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 21
Member Function of Queue
template <class KeyType>
Queue <Keytype>::Queue(int MaxQueuesize):MaxSize(MaxQueueSize)
{
queue = new KeyType[MaxSize];
front = rear = -1;
}

template<class KeyType>
inline Boolean Queue <Keytype>::IsFull();
{
if (rear == MaxSize-1) return TRUE;
else return FALSE;
} template<KeyType>
inline Boolean Queue<KeyType>::IsEmpty()
{
if(front == rear) return TRUE;
else return FALSE;
}
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 22
Member Function of Queue
template <class KeyType>
void Queue <Keytype> ::Push(const KeyType &x) // push x to the queue
{
if(IsFull()) QueueFull();
else queue[++rear]=x;
}

template <class KeyType>


KeyType *Queue <Keytype> ::Delete(KeyType &x)
// remove front element from the queue
{
if(IsEmpty()) QueueEmpty();
else x=queue[++front];
return &x;
}

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 23
Job Scheduling (Fig. 3.5)

•In operating system


–if priorities are not used, the jobs are processed in the
order they enter the system
front Rear Q[0] Q[1] Q[2] Q[3] Q[4] Comments
-1 -1 queue empty Initial
-1 0 J1 Job1 joins Q
-1 1 J1 J2 Job2 joins Q
-1 2 J1 J2 J3 Job3 joins Q
0 2 J2 J3 Job1 leaves Q
0 3 J2 J3 J4 Job4 joins Q
1 3 J3 J4 Job2 leaves Q
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 24
Job Scheduling

•Worst Case Scenario


– It takes n-1 steps to Push a new job

front rear Q[0] Q[1] Q[2] …. Q[n-1] Comments


-1 n-1 J1 J2 J3 …. Jn Initial
0 n-1 J2 J3 …. Jn Delete J1
-1 n-1 J2 J3 J4 …. Jn+1 Push Jn+1
Jobs J2 through
Jn are moved

0 n-1 J3 J4 … Jn+1 Delete J2


-1 n-1 J3 J4 j5 … Jn+2 Push Jn+2

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 25
Circular Queues
• Queue size = n,
• Jobs: J1, J2, J3, J4

4 J4 4
J3 n-4 n-4
3 3 J1
J2
J1
n-3 J2 n-3
2 2 J4 J3
n-2 n-2
1 1
0 n-1 0 n-1

front = 0; rear = 4 front = n-4; rear = 0

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 26
Circular Queues
• To solve the issue of moving elements in queue
– circular queue assigns next element to q[0] when
rear == MaxSize – 1.
– Pointer front will always point one position
counterclockwise from the first element in the queue.
– Queue is empty when front == rear.
But it is also true when queue is full.
This will be a problem.

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 27
Circular Queues
• To resolve the issue (when front == rear) on
whether the queue is full or empty,
– one way is to use only MaxSize – 1 elements in the queue
at any time.
– Each time when Pushing an item to the queue, a newrear is
calculated before Pushing the item.
If newrear == front, then the queue is full.
• Another way to resolve the issue
– is using a flag to keep track of the last operation.
– The drawback of the method is it tends to slow down Push
and Delete function.

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 28
Push an Element to a Circular Q

4 J4 4
J3 n-4 n-4
3 3 J1
J2
J1 n-3 J2 n-3
2 2 J4 J3
n-2 n-2
1 1
0 n-1 0 n-1
front = 0; rear = 4 front = n-4; rear = 0

template <KeyType>
void Queue <KeyType>::Push(const KeyType &x)
{
int new_rear=(rear+1)%MaxSize;
if (front == new_rear) QueueFull();
else queue[rear = new_rear]=x;
}
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 29
Delete an Element from a Circular Q

4 J4 4
J3 n-4 n-4
3 3 J1
J2
J1 n-3 J2 n-3
2 2 J4 J3
n-2 n-2
1 1
0 n-1 0 n-1
front = 0; rear = 4 front = n-4; rear = 0
template <KeyType>
KeyType *Queue <KeyType> ::Delete(const KeyType &x)
// remove the front element from queue
{
if (front == rear) { QueueEmpty(); return(0); }
front = (front+1)%MaxSize;
x = queue[front]; return (&x);
}
2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 30
DeQue
• Definition
– A Double-ended queue (Deque) is a linear list in which
push and delete operations may be made at either end

• Exercise
– Design a data representation that maps a deque into a
one-dimensional array
– Write algorithms to Push and delete elements from
either end of the queue

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 31
SubType & Inheritance in C++
• Inheritance
– Is used to express IS-A relationship between ADTs
– Derived class IS-A base classes
– C++ provides a mechanism called public inheritance
• Ex: class Stack::public Bag
– The inherited members have the same level of access in the
derived class as in the base class
• IS-A relation
– If B inherits from A, then B IS-A A. (A is more general than B)
– VW Beetle IS-A Car; Eagle IS-A Bird
– Chair IS-A furniture, Lion IS-A Mammal
– Rectangle IS-A Polygon
– Stack IS-A Bag

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 32
Inheritance
• A derived class
– inherits all the non-private (e.g., protected and public)
members (data and functions) of the base class.
– Inherited members from public inheritance have the
same level of access in the derived class as they did in
the base class.
• The derived class
– can reuse the implementation of a function in the base
class or implement its own function, with the exception
of constructor and destructor.

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 33
Bag and Stack (old)
class Bag
{
public:
Bag(int MaxSize=defaultSize); // constructor
~Bag(); // destructor
virtual void Push(int);
virtual int *Delete(int&)
virtual Boolean IsFull();
virtual Boolean IsEmpty();
protected:
virtual void Full();
virtual void Empty();
int *array; int MaxSize; int top; // data members
};

class stack:public Bag


Constructor & destructor
{ cannot be reused
public:
Stack(int MaxSize=DefaultSize);
~Stack();
int *Delete(int &); // delete the element from stack
};
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 34
Example of Derived Class (old)
Stack:: Stack (int MaxStackSize) : Bag(MaxStackSize) { }
// Constructor for Stack calls constructor for Bag

Stack::~Stack() { }
// Destructor for Bag is automatically called when Stack is destroyed.
// This ensures that array is deleted.

int* Stack::Delete(int& x)
{ if (IsEmpty()) {Empty(); return 0; }
x = array[top--];
return &x;
}

Example:
Stack s(3); int x

s.Push(1); s.Push(2); b.Push(3);


// Stack::Push is not defined, so use Bag::Push instead
s.Delete(x)
// use Stack::Delete, which calls Bag::IsEmpty and Bag::Empty
// because these have not been redefined in Stack

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 35
Bag and Stack (new)
class Bag
{
public:
Bag(int bagCapacity=10); // constructor
virtual ~Bag(); // destructor

virtual int Size() const;


virtual bool IsEmpty() const;
virtual int Element() const;
virtual void Push(cont int);
virtual void Pop()
protected:
int *array;
int capacity;
int top;
} class stack:public Bag
{
public:
Stack(int stackCapacity=10);
~Stack();
int Top() const;
void Pop(); // delete the element from stack
};
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 36
Example of Derived Class (new)
Stack::Stack(int stackCapacity):Bag(stackCapacity){ }
// Constructor for Stack calls constructor for Bag
Stack::~Stack(){ }
// destructor for Bag is automatically called when Stack is destroyed. const: means that the
function can only
// this ensure that array is deleted
access class member
int Stack::Top() const int Stack::Pop() const data and cannot
{ { change member data
if( IsEmpty( )) throw “Stack is empty.”; if( IsEmpty( )) throw “Stack is empty. Cannot delete”;
return array[top]; top--;
} }
Bag b(3); // uses Bag constructor to create array of size 3
Stack s(3); // uses Stack constructor to create array of size 3
b.Push(1); b.Push(2); b.Push(3);
// use Bag::Push
s.Push(1); s.Push(2); s.Push(3);
// Stack::Push not defined, so use Bag::Push.
b.Pop(); // uses Bag::Pop, which calls Bag::IsEmpty
s.Pop(); // uses Stack::Pop, which calls Bag::IsEmtpy because IsEmpty
// has not been redefined in Stack.
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 37
The Mazing Problem
entrance 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1
1 0 0 0 1 1 0 1 1 1 0 0 1 1 1
0 1 1 0 0 0 0 1 1 1 1 0 0 1 1
1 1 0 1 1 1 1 0 1 1 0 1 1 0 0
1 1 0 1 0 0 1 0 1 1 1 1 1 1 1
X
0 0 1 1 0 1 1 1 0 1 0 0 1 0 1
0 1 1 1 1 0 0 1 1 1 1 1 1 1 1
X
0 0 1 1 0 1 1 0 1 1 1 1 1 0 1
1 1 0 0 0X 1 1 0 1 1 0 0 0 0 X 0
0 0 1 1 1 1 1 0X 0 0 1 1 1 1 0
0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 exit
1: blocked path 0: through path
*Figure 3.11: An example maze (p.153)

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 38
Allowable Moves

NW N NE

[i-1][j-1] [i-1][j] [i-1][j+1]

W [i][j-1] X [i][j+1] E
[i][j]

[i+1][j-1] [i+1][j] [i+1][j+1]


SW S SE

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 39
The Maze Problem (Cont.)
• Stack is used in solving the maze problem for
storing the coordinates and direction.
• Use of another m x p array to mark any position
that has been visited before.

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 40
Coordinates of the Next Move
The coordinates of the following move is computed by the
following data structure N
[i-1][j-1] [i-1][j] [i-1][j+1]
NW NE

[i][j-1] X [i][j+1]
W [i][j] E

struct offsets [i+1][j-1] [i+1][j] [i+1][j+1]


SW
{ S
SE

int x, y;
q move[q].x move[q].y
};
N -1 0
enum directions {
NE -1 1
N, NE, E, SE, S, SW, W, NW
}; E 0 1
SE 1 1
offset move[8];
→ the SW of (i, j) will be (g, h) where S 1 0
g= i + move[SW].x; // e.g., move[5].x SW 1 -1
h= j + move[SW].y; W 0 -1
NW -1 -1
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 41
First Pass at Finding a Path
Through a Maze
Initialize the stack to the maze entrance coordinates and direction east;
while (stack is not empty)
{
(i, j, dir) = coordinates and direction deleted from top of stack;
while (there are more moves from (i, j) )
{
(g, h) = coordinates of next move; // visit the position clockwise
if ((g = = m) && (h = = p)) success; // output the path info. & exit
if ((!maze [g][h]) // legal move
&& (!mark [g][h])) // haven’t been here before
{
mark [g ][h] = 1;
dir = next direction to try; an item of the stack:
add (i, j, dir) to top of stack; struct items {
(i, j, dir) = (g, h, N) ; int x, y, dir;
} }
}
}
cout << "No path in maze." << endl;
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 42
Example: A Maze Problem

Row0 Current Next Stack


Position Legal Move operation
Row1 0 0 0
(1,1) (1,2,E) Push(1,1,E)
Row2 0 1 1
(1,2) (1,3,E) Push(1,2,E)
Row3 1 0 0 (1,3) No legal move Pop to backtrack

Row4
(1,2) (2,1,SW) Push(1,2,SW)
(2,1) (3,2,SE) Push(2,1,SE)
C0 C1 C2 C3 C4
(3,2) (3,3,E) Pop out the entire stack
Stack success!

(2,1,SE)
(1,2,SW) Complete path:
(1,1,E) (3,3)  (3,2,E)  (2,1,SE)  (1,2,SW)  (1,1,E)

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 43
an item of the stack:
struct items {
int x, y, dir;
}

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1
1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 1
1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1
1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1
1 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1
1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1
1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1
1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1
1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1
1 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 1
1 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 44


void Path(const int m, const int p)
{ // 輸出迷宮的一個路徑(如果有的話); maze[0][i] = maze[m+1][i] =
// maze[j][0] = maze[j][p+1] = 1, 0  i  p+1, 0  j  m+1。
// 從 (1, 1) 開始
an item of the stack:
mark[1][1] = 1;
Stack<Items> stack(m*p);
struct items {
Items temp(1, 1, E); int x, y, dir;
// 設定 temp.x、temp.y、與temp.dir }
Stack.Push(temp);
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 while (!stack.IsEmpty( )) // 堆疊不是空的就繼續做
1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 {
temp = stack.Top( ); // fetch the upmost item
1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1
stack.Pop( ); // 彈出
1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 int i = temp.x; int j = temp.y; int d = temp.dir; // (i, j) current position
1 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 while (d < 8) // 往前移動
1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 {
1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 int g = i + move[d].a; int h = j + move[d].b; // (g, h) next try
1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 if ((g = = m) && (h = = p)) { // 抵達出口
1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 // 輸出路徑
1 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 1 cout << stack;
cout << i << " " << j << endl; // 路徑上的上兩個方塊
1 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1
cout << m << " " << p << endl;
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
return;
}
if ((!maze [g][h]) && (!mark [g][h])) { // 新位置
mark[g][h] = 1;
temp.x = i; temp.y = j; temp.dir = d+1;
stack.Push(temp); // 加入堆疊
i = g; j = h; d = N; // (i, j) 移到 (g, h)
else d++; // 試下一個方向
}
}
cout << "No path in maze." << endl;
2022/3/21 J.-J.} Chen, EE NTUST Stack & Queue 45
Evaluation of Expressions
• X=A/B-C+D*E-A*C
with A=4,B=2,C=2, D=E=3
• Interpretation 1 → * and / have higher priorities
((4/2)- 2) + (3*3) - (4*2) = 0 + 8 + 9 = 1

• Interpretation 2 → + and – have higher priorities


(4/(2-2+3))*(3-4)*2 = (4/3) * (-1) * 2=-2.66666…

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 46
Priority of Operands in C++
Evaluation of operators of the same priority will proceed left to right
e.g., A/B*C→(A/B) *C

Priority Operator
1 Unary minus, !
2 *,/,%
3 +,-
4 <,<=,>,>=
5 ==,!=
6 &&
7 ||

with above priorities, we know how X=A/B-C+D*E-A*C will be


evaluated, i.e, X=(((A/B)-C)+(D*E))-(A*C)

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 47
Postfix Notation
• Compiler
– Translates an expression into a sequence of machine codes
– It first re-writes the expression into a form called postfix
notation
• Infix notation
– The operations come in-between operands
• Postfix notation
– The operators appear after its operands
• Example
– Infix: A/B-C+D*E-A*C
– Postfix: AB/C-DE*+AC*-

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 48
Evaluation of Postfix Notation
• Scanning the notation from left to right
• Store temporary result in Ti, i1
Infix: A/B-C+D*E-A*C
Original expression: AB/C-DE*+AC*-
Operation Postfix
T1 = A/B T1 C-DE*+AC*-
T2 = T1 – C T2 DE*+AC*-
T3 = D*E T2 T3 +AC*-
T4 = T2 + T3 T4 AC*-
T5 = A*C T4 T5 -
T6 = T4 - T5 T6

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 49
The virtues of Postfix Notation
• Evaluation is easier than others on postfix
notation
– The need for parenthesis is eliminated
– The priority of operations is no longer relevant
– Evaluation of each operator
• Pop correct number of operands from the stack
• Perform the operation
• Push the results onto the stack

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 50
Evaluation Algorithm
(for postfix expression)
void Eval(Expression e)
// Evaluate the postfix expression e。It is assumed that the last token (a token
// is either an operator, operand, or ‘#’) in e is ‘#’. A function NextToken is
// used to get the next token from e. The function uses the stack stack
{
Stack<Token>stack; // initialize stack
for (Token x = NextToken(e); x!= ‘#’; x=NextToken(e))
if (x is an operand) stack.Push(x) // add to stack
else { // operator
remove the correct number of operands for operator x from stack;
perform the operation x and store the result (if any) onto the stack;
}
} // end of eval
Program 3.18, Evaluating postfix expressions
(p.150)

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 51
Infix to Postfix
• Algorithm
– Fully parenthesize the expression
– Move all operators so that they replace their
corresponding right parenthesis
– Delete all parentheses
• Example: A/B-C+D*E-A*C
→ ((((A/B)-C)+(D*E))-(A*C))

→AB/C-DE*+AC*-

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 52
Example1: infix to postfix
• Translate A+BC to ABC+
– All operands go directly to the output
– When the input tokens are exhausted → all operators
in the stack will be popped out

Next token Stack Output


None Empty None
A Empty A
+ + A
B + AB
 + AB
The operator  has a higher priority than +, so it is placed on top of +
C + ABC
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 53
Example2: infix to postfix
• Translate A(B+C)/D to ABC+D/
Next Token Stack Output
None Empty None
A Empty A
  A
( ( A
B ( AB
+ (+ AB
C (+ ABC
At this point we want to unstack down to the
corresponding “(“ & then delete “(“ and “)”
)  ABC+
/ / ABC+
D / ABC+D/
Done Empty ABC+D/
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 54
Priority-Based Stack Operation
• Left Parenthesis
– Behaves as an operator with high priority when it is not in
the stack →in-coming priority, icp(‘(‘)=0
– Behaves as one with low priority when it is in the stack →
in-stack priority, isp(‘(‘)=8
– Only the matching right parenthesis can get a in-stack left
parenthesis unstacked
• Summary
– Operators are taken out of the stack as long as their in-
stack priority s is numerically less than or equal to the in-
coming priority of the new operator
– Assuming that the icp(‘#’)=8

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 55
Converting infix to postfix
void postfix(expression e)
// output the postfix form of the infix expression e.Nexttoken
// and stack are as in function eval (Program 3.18). It is assumed that
// the last token in e is ‘#’. Also, ‘#’ is used at the bottom of the stack
{ stack<token>stack; // initialize stack
token y;
stack.Add(‘#’);
for (token x = NextToken(e); x != ‘#’; x = NextToken(e))
{ if (x is an operand) cout << x;
else if (x = =’)’) // unstack until ’(‘
for (y=*stack.Delete(y); y != ‘(‘; y=*stack.Delete(y)) cout << y;
else { // x is an operator
for (y=*stack.Delete(y); isp(y) <= icp(x); y=*stack.Delete(y)) cout <<y;
stack.Add(y); // unstack the last y that was unstacked
stack.Add(x); // push the current x into stack
}
} Higher value
// end of expression; empty the stack → lower priority
while(!stack.IsEmpty( )); cout << *stack.Delete(y);
} // end of postfix

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 56
Converting infix to postfix
void Postfix(Expression e)
// output the postfix form of the infix expression e.Nexttoken
// and stack are as in function eval (Program 3.18). It is assumed that
// the last token in e is ‘#’. Also, ‘#’ is used at the bottom of the stack
{
Stack<Token>stack; // initialize stack
stack.Push(‘#’);
for (Token x = NextToken(e); x != ‘#’; x = NextToken(e))
if (x is an operand) cout << x;
else if (x = =’)’) // unstack until ’(‘
{ for (;stack.Top( ) != ‘(‘; stack.Pop( ))
cout << stack.Top( );
stack.Pop( ); // unstack ’(‘ Higher value
} → lower priority
else { // x is an operator
for (; isp(stack.Top( )) <= icp(x); stack.Pop( ))
cout << stack.Top( );
stack.Push(x);
}
// end of expression; empty the stack
for (; !stack.IsEmpty( ); cout << stack.Top( ), stack.Pop( ));
cout << endl;
}
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 57
Multiple Stacks & Queues
• Two stacks
0 1 2 3 4 m-4 m-3 m-2 m-1

m / n  − 1

Stack A Stack B

• More than two stacks (n)


– memory is divided into n equal segments

– boundary[stack_no], top[stack_no]

0  stack_no < MAX_STACKS

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 58
Multiple Stacks
• Divide memory into segments for n stacks

0 m / n − 1 2 m / n  − 1 m-1

stack0 Stack 1 Stack n-1

b[0] b[1] b[2] b[n]

t[0] t[1] t[2] t[n]

2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 59


Operations of Multiple Stacks
0 m / n − 1 2 m / n  − 1 m-1

stack0 Stack 1 Stack n-1

b[0] b[1] b[2] b[n]

t[0] t[1] t[2] t[n]

template <class type>


type* Delete(const int I, const type &x)
template <class type> //Delete top element in the i-th stack
void Push(const int i, const type &x) {
// Push x to the i-th stack if( t[i]==b[i]) {
{ StackEmpty(i); return();
if(t[i]==b[i+1]) StackFull(i); }
else M[++t[i]]=x; x=M[t[i]--];
} return(&x)
}

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 60
StackFull Function
• Find the least j, i < j < n, s.t. t[j] < b[ j +1]
(find free space from right portion)
or, largest j, 0  j < i, s.t. t[j] < b[ j +1]
(find free space from left portion)
b[i+2] t[i+2]

b[i+1] t[i+1]
b[0] t[0] b[1] t[1] b[i] t[i] b[j] t[j] b[j+1] b[n]
X
meet
b=boundary, t=top
Find free space from right or left

*Figure 3.15: Configuration when stack i meets stack i+1,


but there is still free space elsewhere in M (p. 156)
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 61
Appendix

2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 62


Virtual vs. non-virtual function
• Difference
– the non-virtual member functions are resolved at
compile time →static binding.
– The virtual member functions are resolved during run-
time → dynamic binding.

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 63
Homeworks
• Write the postfix & prefix
form of the following
expressions:

(a) A  B  C
(b) − A + B − C + D
(c ) A * − B + C
(d ) ( A + B)  D + E / ( F + A * D) + C
(e) A & & B || C ||!( E  F ) (assuming C++ precedence)
( f ) !( A & &!(( B  C ) || (C  D))) || (C  E )

2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 64


Postfix
(a ) ((A  B )  C ) → AB * C *
(b) ((( − A + B ) − C ) + D ) → A − B + C − D +
(c) (((A * (− B )) + C ) → AB − *C +
(d ) ( A + B )  D + E /( F + A * D) + C
→ AB + D * EFAD * + / + C +
(e) A & & B || C || !( E  F ) (assuming C++ precedence)
→ AB & & || C || EF  !
→ AB & &C || EF  !||
( f ) !( A & &!(( B  C ) || (C  D))) || (C  E )
→ !( A&&!(BC  || CD )) || CE 
→ ABC  CD || !& &!CE ||
J.-J. Chen, EE NTUST
2022/3/21 Stack & Queue 65
prefix

(a ) ** ABC
(b) + − + uABCD (u represents the unary minus)
(c) + * AuBC
(d) + + * + ABD / E + F * ADC
(e) → &&AB || C || !>EF
→ || || && ABC ! > EF
(f) → || ! && A ! || < BC > CD < CE

2022/3/21 J.-J. Chen, EE NTUST Stack & Queue 66


Appendix A
• Tokenize

J.-J. Chen, EE NTUST


2022/3/21 Stack & Queue 67

You might also like