700 likes | 828 Views
Data Structures: Stacks Queues. Stack ADT: What is a Stack?. 0. a stack is a varying-length , collection of homogeneous elements Insertion and Deletion only occurs at the front (or top) of the stack. Push and Pop Last In First Out (LIFO) Structure How might we implement a stack?.
E N D
Stack ADT: What is a Stack? 0 • a stack is a varying-length, collection of homogeneous elements • Insertion and Deletion only occurs at the front (or top) of the stack. • Push and Pop • Last In First Out (LIFO) Structure • How might we implement a stack?
Array Stack Implementation 0 • First element on can go in first array position, the second in the second position, etc. • The top of the stack is the index of the last element added to the stack • Stack elements are stored in an array • Stack element is accessed only through top • To keep track of the top position use a variable called top
Array Stack Implementation 0 • Because a stack is homogeneous you can use an array to implement a stack • Can use static array if maximum size known in advance • Can dynamically allocate array to specify size of the array • Data movement more efficient than array lists due to no access to middle elements
0 Class Interface Diagram (static array) StackType class Private data: top [MAX_ITEMS-1] . . . [ 2 ] [ 1 ] items [ 0 ] StackType MakeEmpty IsEmpty IsFull Push Pop
const int MAX_ITEMS = 50; class StackType { public: StackType( ); // Default constructor. // POST: Stack is created and empty. void MakeEmpty( ); // PRE: None. // POST: Stack is empty. bool IsEmpty() const; // PRE: Stack has been initialized. // POST: Function value = (stack is empty) bool IsFull( ) const; // PRE: Stack has been initialized. // POST: Function value = (stack is full) void Push( char newItem ); // PRE: Stack has been initialized and is not full. // POST: newItem is at the top of the stack. char Pop( ); // PRE: Stack has been initialized and is not empty // POST: top element has been removed from the stack // returns a copy of removed element private: int top; char items[MAX_ITEMS]; // static array of characters };
StackType::StackType( ) // Default Constructor { top = -1; } void StackType::MakeEmpty() { top = -1; } bool StackType::IsEmpty( ) const { return ( top == -1 ); } bool StackType::IsFull() const { return ( top == MAX_ITEMS-1 ); } 8
void StackType::Push ( char newItem ) //------------------------------------------------------ // PRE: Stack has been initialized and is not full // POST: newItem is at the top of the stack. //------------------------------------------------------ { top++; items[top] = newItem; } char StackType::Pop ( ) //------------------------------------------------------ // PRE: Stack has been initialized and is not empty // POST: Top element has been removed from stack. // returns a copy of removed element. //------------------------------------------------------ { char value = items[top]; top--; return value; } 9
Tracing Client Code letter ‘V’ char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop();
Tracing Client Code letter ‘V’ char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top -1 [MAX_ITEMS-1] . . . [ 2 ] [ 1 ] items [ 0 ]
Tracing Client Code ‘V’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 0 [MAX_ITEMS-1] . . . [ 2 ] [ 1 ] items [ 0 ] ‘V’
Tracing Client Code ‘V’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 1 [MAX_ITEMS-1] . . . [ 2 ] [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘V’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 2 [MAX_ITEMS-1] . . . [ 2 ] ‘S’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘V’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 2 [MAX_ITEMS-1] . . . [ 2 ] ‘S’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘S’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 1 [MAX_ITEMS-1] . . . [ 2 ] ‘S’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘S’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 2 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘S’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 2 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘K’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 1 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘K’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 1 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘C’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 0 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘C’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top 0 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Tracing Client Code ‘V’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top -1 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
Test Fails – End Trace ‘V’ letter char letter = ‘V’; StackType charStack; charStack.Push(letter); charStack.Push(‘C’); charStack.Push(‘S’); if ( !charStack.IsEmpty( )) letter = charStack.Pop(); charStack.Push(‘K’); while (!charStack.IsEmpty( )) letter = charStack.Pop(); Private data: top -1 [MAX_ITEMS-1] . . . [ 2 ] ‘K’ [ 1 ] ‘C’ items [ 0 ] ‘V’
A Dynamic Array Class • Use dynamic array to hold items • Store capacity and top in private data • Resize array to accommodate unlimited size • done in Push member • data movement in resize is costly… • Provide parameterized constructor, copy constructor, and destructor • Provide same functionality so client code is same
class StackType { public: StackType( ); StackType( int sizeIn ); // Parameterized constructor // POST: Stack is allocated and empty StackType( StackType& otherStack ); // Copy constructor // POST: Stack is a deep copy of target stack ~StackType( ); // Destructor // POST: Stack is deallocated void MakeEmpty( ); bool IsEmpty() const; bool IsFull( ) const; void Push( char newItem ); char Pop( ); private: int top, capacity; char *items; // dynamicic array of characters };
StackType::StackType( ) // Default Constructor { capacity = 50; items = new char[capacity]; top = -1; } StackType:: StackType( int sizeIn ) // Parameterized constructor { capacity = sizeIn; items = new char[capacity]; top = -1; } StackType:: StackType( StackType& otherStack ) //Copy Constructor { capacity = otherStack.capacity; Delete [] items; //prevent memory leak items = new char[capacity]; top = otherStack.top; for(int i=0; i<=top; i++) items[i] = otherStack.items[i]; } 27
StackType::~StackType( ) // Destructor { delete [] items; } void StackType::MakeEmpty() { top = -1; } bool StackType::IsEmpty( ) const { return ( top == -1 ); } bool StackType::IsFull() const { return false; //stack cannot get full due to resizing... } 28
void StackType::Push ( char newItem ) //------------------------------------------------------ // PRE: Stack has been initialized // POST: newItem is at the top of the stack. // stack resized if necessary //------------------------------------------------------ { if( top == capacity-1 ) //resize necessary { capacity = capacity + 50; //you can change resize factor char *temp = new char[capacity]; //allocate new stack array for( int i=0; i<=top; i++ ) //copy items to new stack array temp[i] = items[i]; delete [] items; //deallocate old stack array items = temp; //redirect pointer to new stack array } //perform push as usual top++; items[top] = newItem; } 29
char StackType::Pop ( ) //------------------------------------------------------ // PRE: Stack has been initialized and is not empty // POST: Top element has been removed from stack. // returns a copy of removed element. //------------------------------------------------------ { char value = items[top]; top--; return value; } 30
Linked Implementation of Stacks 0 • Static array only allows fixed number of elements • Dynamic arrays can resize, but inefficient • Linked nodes can dynamically organize data • In a linked representation, there is a pointer to top element in stack
StackType MakeEmpty Private data: topPtr IsEmpty ‘C’ ‘V’ IsFull Push Pop ~StackType 0 class StackType
char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’); Tracing Client Code 0 ‘V’ letter
Tracing Client Code 0 letter ‘V’ Private data: topPtr NULL char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’);
Tracing Client Code 0 letter ‘V’ Private data: topPtr ‘V’ char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’);
Tracing Client Code 0 letter ‘V’ Private data: topPtr ‘C’ ‘V’ char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’);
Tracing Client Code 0 letter ‘V’ Private data: topPtr ‘S’ ‘C’ ‘V’ char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’);
Tracing Client Code 0 letter ‘V’ Private data: topPtr ‘S’ ‘C’ ‘V’ char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’);
Tracing Client Code 0 letter ‘S’ Private data: topPtr ‘C’ ‘V’ char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’);
Tracing Client Code 0 letter ‘S’ Private data: topPtr ‘K’ ‘C’ ‘V’ char letter = ‘V’; StackType myStack; myStack.Push(letter); myStack.Push(‘C’); myStack.Push(‘S’); if ( !myStack.IsEmpty( ) ) letter = myStack.Pop( ); myStack.Push(‘K’);
Modifying a Linked List Classfor Stack Functionality • How does the stack ADT differ from the list ADT? • Where are the items accessed? • “Data Flow Characteristics” • How might we change features of the linked list class so that it fulfills the stack ADT? • Add Push and Pop • Remove Insert/Delete
Implementing Push 0 void Stack::Push ( /* in */ char item ) // Adds item to the top of the stack. { NodeType* location; location = new NodeType; location->info = item; location->next = head; head = location; } NOTE: This is the same code as the existing InsertFront member... 42
Implementing Pop 0 char Stack::Pop ( ) // removes item at top of the stack and returns it { NodeType* tempPtr; char item = head->info; tempPtr = head; head = head->next; delete tempPtr; return item; } NOTE: This is the same code as the existing DeleteFront member... 43
Alternate Implementations 0 void Stack::Push ( /* in */ char item ) { InsertFront(item); } char Stack::Pop ( ) { return DeleteFront(); } 44
The C++ stack Class • Part of Standard Template Library • Must include stack library #include <stack> • Declare the stack stack <type>stack-name; • E.g. stack <string> nameStack; stack <char> s; • Use to compare/test YOUR stack classes…
Application of Stacks: POSTFIX EXPRESSIONS CALCULATOR 0 • In infix notation: • Operator is written between the operands • For example, a+b • Lukasiewicz discovered parentheses can be omitted if operators are written • Before operands (prefix or Polish notation; for example, + a b) • After the operands (suffix, postfix, or reverse Polish notation; for example, a b +) • Can use a stack to evaluate postfix
Postfix Example 0 • The postfix method uses a stack. To process the infix expression • 5 – (3 + 1) * 2 • In postfix, it would be represented by • 5 3 1 + 2 * - • A postfix machine processes an expression using the algorithm: • Push values • If an operator: • pop operand 2 • pop operand 1 • perform the operation • operand 1 operator operand 2 • push the result
Stack application: syntax checking 0 A compiler uses a stack to check for correct syntax of tokens that come in pairs: () [] {} The logic: Left token: push it on a stack Right token: Pop off of stack For correct syntax, there must be a matching left token on the stack when a pop occurs, and at the end of the statement, the stack must be empty
Examples of Stack Syntax Checking 0 Sample statements: {x = (a*(b+(c[3])))} {x=(a*(b+c[2])})
Queue ADT: What is a Queue? 0 • a queue is a varying-length, collection of homogeneous elements • Insertion only occurs at the rear of the queue, Deletion only occurs at the front. • Enqueue and Dequeue • First In First Out (FIFO) Structure • How might we implement a queue?