Chapter 5 ADTs Stack and Queue. Stacks of Coins and Bills.

73
Chapter 5 ADTs Stack and Queue

Transcript of Chapter 5 ADTs Stack and Queue. Stacks of Coins and Bills.

Chapter 5ADTs Stack and

Queue

Stacks of Coins and Bills

Stacks of Boxes and Books

TOP OF THE STACK TOP OF THE STACK

Definition of Stack

• Logical (or ADT) level: A stack is an ordered group of homogeneous items (elements), in which the removal and addition of stack items can take place only at the top of the stack.

• A stack is a LIFO “last in, first out” structure.

Stack ADT Operations

• MakeEmpty -- Sets stack to an empty state.

• IsEmpty -- Determines whether the stack is currently empty.

• IsFull -- Determines whether the stack is currently full.

• Push (ItemType newItem) -- Throws exception if stack is full; otherwise adds newItem to the top of the stack.

• Pop -- Throws exception if stack is empty; otherwise

removes the item at the top of the stack.

• ItemType Top -- Throws exception if stack is empty; otherwise returns a copy of the top item

ADT Stack Operations

Transformers • Push• Pop

Observers • IsEmpty

• IsFull

change state

observe state

class StackType{public:

StackType( );

bool IsFull () const;

bool IsEmpty() const;

void Push( ItemType item );

void Pop();

private: ItemType Top();

private:int top;ItemType items[MAX_ITEMS];

};

What are the

pre and post

conditions?

// File: StackType.cpp

#include "StackType.h" #include <iostream>StackType::StackType( ){ top = -1;}bool StackType::IsEmpty() const{ return(top == -1);}

bool StackType::IsFull() const{ return (top = = MAX_ITEMS-1);}

void StackType::Push(ItemType newItem){

if( IsFull() ) throw FullStack():top++;items[top] = newItem;

} void StackType::Pop(){

if( IsEmpty() ) throw EmptyStack();

top--;}

ItemType StackType::Top(){

if (IsEmpty()) throw EmptyStack();

return items[top];}

Class Interface Diagram(Memory reversed to better illustrate concept)

StackType class

StackType

Pop

Push

IsFull

IsEmpty

Private data:

top

[MAX_ITEMS-1] . . .

[ 2 ]

[ 1 ]

items [ 0 ]

Top

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

Private data:

top

[MAX_ITEMS-1] . . .

[ 2 ]

[ 1 ]

items [ 0 ]

letter ‘V’

Tracing Client Code

letter ‘V’

Private data:

top -1

[MAX_ITEMS-1] . . .

[ 2 ]

[ 1 ]

items [ 0 ]

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top 0

[MAX_ITEMS-1] . . .

[ 2 ]

[ 1 ]

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top 1

[MAX_ITEMS-1] . . .

[ 2 ]

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top 2

[MAX_ITEMS-1] . . .

[ 2 ] ‘S’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top 2

[MAX_ITEMS-1] . . .

[ 2 ] ‘S’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top 1

[MAX_ITEMS-1] . . .

[ 2 ] ‘S’

[ 1 ] ‘C’

items [ 0 ] ‘V’0

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top 2

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top 2

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘K’

Private data:

top 2

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘K’

Private data:

top 1

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘K’

Private data:

top 1

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘C’

Private data:

top 0

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘C’

Private data:

top 0

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Tracing Client Code

letter ‘V’

Private data:

top -1

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

End of Trace

letter ‘V’

Private data:

top -1

[MAX_ITEMS-1] . . .

[ 2 ] ‘K’

[ 1 ] ‘C’

items [ 0 ] ‘V’

char letter = ‘V’;StackType charStack;

charStack.Push(letter);

charStack.Push(‘C’);

charStack.Push(‘S’);

if ( !charStack.IsEmpty( )) charStack.Pop( );

charStack.Push(‘K’);

while (!charStack.IsEmpty( )){ letter = charStack.Top(); charStack.Pop(0)}

Another Stack Implementation

• One advantage of an ADT is that the implementation can be changed without the program using it knowing about it.

• The dynamic array implementation of the stack has a weakness -- the maximum size of the stack is passed to the constructor as parameter.

• Instead we can dynamically allocate the space for each stack element as it is pushed onto the stack.

ItemType is char

class StackType

StackType

Top

Pop

Push

IsFull

IsEmpty Private data:

topPtr

~StackType

‘C’ ‘V’

class StackType

StackType

Top

Pop

Push

IsFull

IsEmpty Private data:

topPtr

~StackType

23.4 -7.9

ItemType is float

ItemType is stringclass StackType

StackType

Top

Pop

Push

IsFull

IsEmpty Private data:

topPtr

~StackType

cat dog

Tracing Client Code

letter ‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter ‘V’

Private data:

topPtr NULL

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘V’

‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘C’ ‘V’

‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘S’ ‘ C’ ‘ V’

‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘S’ ‘ C’ ‘V’

‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘C’ ‘V’

‘S’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘C’ ‘V’

‘S’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘V’

‘C’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘V’

‘C’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr

‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr

‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

Tracing Client Codeletter

Private data:

topPtr ‘K’

‘V’

char letter = ‘V’;

StackType myStack;

myStack.Push(letter);

myStack.Push(‘C’);

myStack.Push(‘S’);

If (!myStack.IsEmpty() ){ letter = myStack.Top( ); myStack.Pop();}

myStack.Push(‘K’);

// DYNAMICALLY LINKED IMPLEMENTATION OF STACK Struct NodeType; //Forward

declaration

class StackType{public: //Identical to previous implementationprivate: NodeType* topPtr;};...Struct NodeType {

ItemType info;NodeType* next;

};

Adding newItem to the stack

newItem = ‘B’;NodeType* location;location = new NodeType<char>;location->info = newItem;location->next = topPtr;topPtr = location;

topPtr ‘X’ ‘C’ ‘L’

‘B’

newItem

Adding newItem to the stack

newItem = ‘B’;NodeType* location;location = new NodeType<char>;location->info = newItem;location->next = topPtr;topPtr = location;

topPtr ‘X’ ‘C’ ‘L’

‘B’newItem

location

Adding newItem to the stack

newItem = ‘B’;NodeType* location;location = new NodeType<char>;location->info = newItem;location->next = topPtr;topPtr = location;

topPtr ‘X’ ‘C’ ‘L’

‘B’newItem

location

Adding newItem to the stack

newItem = ‘B’;NodeType* location;location = new NodeType<char>;location->info = newItem;location->next = topPtr;topPtr = location;

topPtr ‘X’ ‘C’ ‘L’

‘B’newItem

location ‘B’

Adding newItem to the stack

newItem = ‘B’;NodeType* location;location = new NodeType<char>;location->info = newItem;location->next = topPtr;topPtr = location;

topPtr ‘X’ ‘C’ ‘L’

‘B’newItem

location ‘B’

Adding newItem to the stack

newItem = ‘B’;NodeType* location;location = new NodeType<char>;location->info = newItem;location->next = topPtr;topPtr = location;

topPtr ‘X’ ‘C’ ‘L’

‘B’newItem

location ‘B’

void StackType::Push ( ItemType newItem )// Adds newItem to the top of the stack.

{ if (IsFull()) throw FullStack(); NodeType* location; location = new NodeType<ItemType>; location->info = newItem; location->next = topPtr; topPtr = location;}

Implementing Push

Do we need IsFull?

Deleting item from the stack

NodeType* tempPtr;

item = topPtr->info;tempPtr = topPtr;topPtr = topPtr->next;delete tempPtr;

topPtr ‘B’ ‘X’ ‘C’ ‘L’

tempPtr

item

Deleting item from the stack

NodeType* tempPtr;

item = topPtr->info;tempPtr = topPtr;topPtr = topPtr->next;delete tempPtr;

topPtr

item

‘B’ ‘X’ ‘C’ ‘L’

tempPtr

‘B’

Deleting item from the stack

NodeType* tempPtr;

item = topPtr->info;tempPtr = topPtr;topPtr = topPtr->next;delete tempPtr;

topPtr

item

‘B’ ‘X’ ‘C’ ‘L’

tempPtr

‘B’

Deleting item from the stack

NodeType* tempPtr;

item = topPtr->info;tempPtr = topPtr;topPtr = topPtr->next;delete tempPtr;

topPtr

item

‘B’ ‘X’ ‘C’ ‘L’

tempPtr

‘B’

Deleting item from the stack

NodeType<ItemType>* tempPtr;

item = topPtr->info;tempPtr = topPtr;topPtr = topPtr->next;delete tempPtr;

topPtr

item

‘X’ ‘C’ ‘L’

tempPtr

‘B’

void StackType::Pop() // Remove top item from Stack.{ if (IsEmpty())

throw EmptyStack(); else {

NodeType* tempPtr; tempPtr = topPtr;

topPtr = topPtr ->next; delete tempPtr;

}}

ItemType StackType::Top() // Returns a copy of the top item in the stack.{

if (IsEmpty()) throw EmptyStack();

else return topPtr->info;

}

Implementing Pop / Top

Implementing IsFullbool StackType::IsFull() const

// Returns true if there is no room for another

// ItemType on the free store; false otherwise

{

NodeType* location;

try

{

location = new NodeType;

delete location;

return false;

}

catch(std::bad_alloc exception)

{

return true;

}

}

Example of a Queue

What is a Queue?

• Logical (or ADT) level: A queue is an ordered group of homogeneous items (elements), in which new elements are added at one end (the rear), and elements are removed from the other end (the front).

• A queue is a FIFO “first in, first out” structure.

Queue ADT Operations

• MakeEmpty -- Sets queue to an empty state.

• IsEmpty -- Determines whether the queue is currently empty.

• IsFull -- Determines whether the queue is currently full.

• Enqueue (ItemType newItem) -- Adds newItem to the rear of the queue.

• Dequeue (ItemType& item) -- Removes the item at the

front of the queue and returns it in item.

ADT Queue Operations

Transformers • MakeEmpty • Enqueue• Dequeue

Observers • IsEmpty

• IsFull

change state

observe state

typedef char ItemType; class QueType { public: QueType(int max); // max is the size of the queue. QueType(); // Default size of 500. ~QueType(); void MakeEmpty(); bool IsEmpty() const; bool IsFull() const; void Enqueue(ItemType item); void Dequeue(ItemType& item);

Public Interface of QueType

SIMPLE ARRAY IMPLEMENTATION

QueType

~QueType

Enqueue

Dequeue . . .

class QueType

Private Data:

front 1

rear 4

maxQue 5

items ‘C’ ‘X’ ‘J’

items [0] [1] [2] [3] [4]

RE

SE

RV

ED

What is the private part of class QueType for this design?

What troubles do we encounter?

DYNAMIC ARRAY IMPLEMENTATION

QueType

~QueType

Enqueue

Dequeue . . .

class QueType

Private Data:

front 1

rear 4

maxQue 5

items‘C’ ‘X’ ‘J’

items [0] [1] [2] [3] [4]

RE

SE

RV

ED

What is the private part of class QueType for this design?

Does this design have the same problems as the previous design?

class QueType

QueType

~QueType

Enqueue

Dequeue . . .

Private Data:

qFront

qRear

‘C’ ‘Z’ ‘T’

What is the private part of class QueType for this design?

CountedQueType inherits from QueType

// DERIVE CLASS CountedQueType FROM BASE CLASS QueType

class CountedQueType : QueType;{public: CountedQueType( ); void Enqueue( ItemType newItem ); void Dequeue( ItemType& item ); int GetLength( ) const; // Returns number of items on the counted queue.

private: int length;};

What additional fields does CountedQueType need?

What functions must be changed?

Comparing Queue Implementations• 80-byte string

• Array:(80 bytes * 101 slots) + (2 bytes * 2 indexes) = 8084 bytes

• Linked queue: 8 bytes for 2 queue pointers, plus (80 bytes + 4 bytes) = 84 bytes / node

• Array requires same amount of memory, regardless of slots used. When elements > 96, queue requires more memory.

• 2-byte integer• Array:

(2 bytes * 101 slots) + (2 bytes * 2 indexes) = 206 bytes

• Lined queue: 8 bytes for 2 queue pointers, plus 2 bytes + 4 bytes = 6 bytes / node

• When elements > 33, queue requires more memory than array

Big-O Comparison of Queue Operations

Dynamic Array Linked ListClass Constructor O(1) O(1)MakeEmpty O(1) O(N)IsFull O(1) O(1)IsEmpty O(1) O(1)Enqueue O(1) O(1)Dequeue O(1) O(1)Destructor O(1) O(N)