definition stack is an ordered collection of data items in which access is possible only at one end...
TRANSCRIPT
Stack and Queue
Stack
Definition• Stack is an ordered collection of data
items in which access is possible only at one end (called the top of the stack).
• Stacks are known as LIFO (Last In, First Out) lists. The last element inserted will be the first to be retrieved
Stack as an AbstractData Type
Basic operations:1. Construct a stack (usually empty)2. Check if stack is empty3. Push: Add an element at the top of the stack4. Pop: Remove the top element of the stack5. Peek: Retrieve the top element of the stack
Adding a plate pushes those below it down in the stack
Removing a plate pops those below it up one position.
Push and Pop Primary operations: Push and Pop Push
◦ Add an element to the top of the stack Pop
◦ Remove the element at the top of the stack
A
top
empty stack
top
top
top
push an element push another
A
B
pop
A
Implementation of Stacks Any list implementation could be used to
implement a stack◦ Arrays (static: the size of stack is given initially)◦ Linked lists (dynamic: never become full)
We will explore implementations based on array and linked list
Array Implementation
Need to declare an array size ahead of time Associated with each stack is TopOfStack
◦ for an empty stack, set TopOfStack to -1 Push
◦ (1) Increment TopOfStack by 1.◦ (2) Set Stack[TopOfStack] = X
Pop◦ (1) Set return value to Stack[TopOfStack]◦ (2) Decrement TopOfStack by 1
These operations are performed in very fast constant time
Stack class
class Stack {public:
Stack(int size = 10); // constructorbool IsEmpty() { return top == -1; }bool IsFull() { return top == maxSize; }double Peek();void push(const double x);double pop();void displayStack();
private:int maxSize // max stack size = size - 1int top; // current top of stackdouble[] values; // element array
};
Stack class Attributes of Stack
◦ maxTop: the max size of stack◦ top: the index of the top element of stack◦ values: point to an array which stores elements of stack
Operations of Stack◦ IsEmpty: return true if stack is empty, return false
otherwise◦ IsFull: return true if stack is full, return false otherwise◦ Peek: return the element at the top of stack◦ Push: add an element to the top of stack◦ Pop: delete the element at the top of stack◦ DisplayStack: print all the data in the stack
Create Stack
The constructor of Stack◦ Allocate a stack array of size. By default, size = 10.
◦ When the stack is full, top will have its maximum value, i.e. size – 1.
◦ Initially top is set to -1. It means the stack is empty.
Stack(int size) {maxTop= size - 1;values = new double[size];top = -1;
}
Although the constructor dynamically allocates the stack array, the stack is still static. The size is fixed after the initialization.
Push Stack
void Push(const double x);◦ Push an element onto the stack◦ If the stack is full, print the error information.◦ Note top always represents the index of the
top element. After pushing an element, increment top.
void push(double x) {if (IsFull())
System.out.println("Error: the stack is full.“); else
values[++top] = x;}
Pop Stack
double Pop()◦ Pop and return the element at the top of the
stack◦ If the stack is empty, print the error
information. (In this case, the return value is useless.)
◦ Don’t forgot to decrement topdouble pop() throw EmptyStackException{
if (IsEmpty()) {System.out.println("Error: the stack is empty.“);throw EmptyStackException;
}else {
return values[top--];}
}
Stack Top
double Peek()◦ Return the top element of the stack◦ Unlike Pop, this function does not remove
the top element
double Peek() throws EmptyStackException{if (IsEmpty()) {
System.out.println("Error: the stack is empty." ); throw EmptyStackException;
}else
return values[top];}
Printing all the elements
void DisplayStack()◦ Print all the elements
void DisplayStack() {System.out.print("top -->“);for (int i = top; i >= 0; i--)
System.out.print( "\t|\t" +values[i] + "\t|\n“); System.out.println("\t|---------------|“);}
}
Using Stack
Initialize stack with 5 items
push(5.0);push(6.5);push(-3.0);push(-8.0);
DisplayStack();
pop(); then print top();pop(); then print top();
result
Stack: Linked List Implementation Push and pop at the head of the list
◦ New nodes should be inserted at the front of the list, so that they become the top of the stack
◦ Nodes are removed from the front (top) of the list Straight-forward linked list implementation
◦ push and pop can be implemented fairly easily, e.g. assuming that head is a reference to the node at the front of the list
List Stack Example
Java CodeStack st = new Stack();st.push(6);
top
6
List Stack Example
Java CodeStack st = new Stack();st.push(6); st.push(1);
top
6
1
List Stack Example
Java CodeStack st = new Stack();st.push(6); st.push(1); st.push(7);top
6
1
7
List Stack Example
Stack st = new Stack();st.push(6); st.push(1); st.push(7); st.push(8); top
6
1
7
8
List Stack Example
Java CodeStack st = new Stack();st.push(6); st.push(1); st.push(7); st.push(8); st.pop();
top
6
1
7
8
List Stack Example
Java CodeStack st = new Stack();st.push(6); st.push(1); st.push(7); st.push(8); st.pop();
top
6
1
7
Stack: ADT List Implementation Push() and pop() either at the beginning or at
the end of ADT List◦ at the beginning:
public void push(Object newItem) { list.insertAtHead(item); } // end pushpublic Object pop() {
return list.removeFromHead();} // end pop
Chapter 5: Stacks 24
Java implementation of StackSpecification of the Stack Abstract Data Type (continued)
Chapter 5: Stacks 25
Text studies two client programs using stacks◦ Palindrome finder◦ Parentheses matcher
A Palindrome is a string that reads the same in either direction◦ Examples: “Able was I ere I saw Elba”
Stack Applications
Chapter 5: Stacks 26
Stack Applications (continued)
Chapter 5: Stacks 27
When analyzing arithmetic expressions, it is important to determine whether an expression is balanced with respect to parentheses◦ (a+b*(c/(d-e)))+(d/e)
Problem is further complicated if braces or brackets are used in conjunction with parenthesis
Solution is to use stacks!
Stack Applications (continued)
Chapter 5: Stacks 28
Stack Applications (continued)
Chapter 5: Stacks 29
Stack Applications (continued)
Chapter 5: Stacks 30
Can use either the ArrayList, Vector, or the LinkedList classes as all implement the List interface
Name of class illustrated in text is ListStack◦ ListStack is an adapter class as it adapts the
methods available in another class to the interface its clients expect by giving different names to essentially the same operations
Implementing a Stack with a List Component
Chapter 5: Stacks 31
Need to allocate storage for an array with an initial default capacity when creating a new stack object
Need to keep track of the top of the stack No size method
Implementing a Stack Using an Array
Chapter 5: Stacks 32
Implementing a Stack Using an Array (continued)
Chapter 5: Stacks 33
We can implement a stack using a linked list of nodes
Implementing a Stack as a Linked Data Structure
Chapter 5: Stacks 34
Vector is poor choice for stack implementation as all Vector methods are accessible
Easiest implementation would be to use an ArrayList component for storing data
All insertions and deletions are constant time regardless of the type of implementation discussed◦ All insertions and deletions occur at one end
Comparison of Stack Implementations
Chapter 5: Stacks 35
Consider two case studies that relate to evaluating arithmetic expressions◦ Postfix and infix notation
Expressions normally written in infix form◦ Binary operations inserted between their
operands A computer normally scans an expression
string in the order that it is input; easier to evaluate an expression in postfix form
Additional Stack Applications
Chapter 5: Stacks 36
Additional Stack Applications (continued)
37
Advantage of postfix form is that there is no need to group subexpressions in parentheses
No need to consider operator precedence
Additional Stack Applications (continued)
38
Evaluating Postfix Expressions
39
Evaluating Postfix Expressions (continued)
Chapter 5: Stacks 40
Evaluating Postfix Expressions (continued)
Chapter 5: Stacks 41
Evaluating Postfix Expressions (continued)
Chapter 5: Stacks 42
Converting from Infix to Postfix
43
Additional Stack Applications (continued)
44
Evaluating Postfix Expressions (continued)
45
Evaluating Postfix Expressions (continued)
46
Queue
Queue Overview Queue ADT Basic operations of queue
◦ Enqueuing, dequeuing. Implementation of queue
◦ Array◦ Linked list
Queue ADT
Like a stack, a queue is also a list. However, with a queue, insertion is done at one end, while deletion is performed at the other end.
Accessing the elements of queues follows a First In, First Out (FIFO) order.◦ Like customers standing in a check-out line in a
store, the first customer in is the first customer served.
The Queue ADT Another form of restricted list
◦ Insertion is done at one end, whereas deletion is performed at the other end
Basic operations:◦ enqueue: insert an element at the rear of the list◦ dequeue: delete the element at the front of the list
First-in First-out (FIFO) list
Enqueue and Dequeue Primary queue operations: Enqueue and
Dequeue Like check-out lines in a store, a queue has a
front and a rear. Enqueue
◦ Insert an element at the rear of the queue Dequeue
◦ Remove an element from the front of the queue
Insert (Enqueue)
Remove(Dequeue) rearfront
Implementation of Queue Just as stacks can be implemented as arrays
or linked lists, so with queues. Dynamic queues have the same advantages
over static queues as dynamic stacks have over static stacks
Queue Implementation of Array
There are several different algorithms to implement Enqueue and Dequeue
Naïve way◦ When enqueuing, the front index is always
fixed and the rear index moves forward in the array.
front
rear
Enqueue(3)
3
front
rear
Enqueue(6)
3 6
front
rear
Enqueue(9)
3 6 9
Queue Implementation of Array
Naïve way◦ When enqueuing, the front index is always
fixed and the rear index moves forward in the array.
◦ When dequeuing, the element at the front the queue is removed. Move all the elements after it by one position. (Inefficient!!!)
Dequeue()
front
rear
6 9
Dequeue() Dequeue()
front
rear
9
rear = -1
front
Queue Implementation of Array
Better way◦ When an item is enqueued, make the rear index
move forward.◦ When an item is dequeued, the front index
moves by one element towards the back of the queue (thus removing the front item, so no copying to neighboring elements is needed).
XXXXOOOOO (rear) OXXXXOOOO (after 1 dequeue, and 1 enqueue)OOXXXXXOO (after another dequeue, and 2 enqueues)OOOOXXXXX (after 2 more dequeues, and 2 enqueues)
(front)
The problem here is that the rear index cannot move beyond the last element in the array.
Implementation using Circular Array
Using a circular array When an element moves past the end of a
circular array, it wraps around to the beginning, e.g.◦ OOOOO7963 4OOOO7963 (after Enqueue(4))◦ After Enqueue(4), the rear index moves from 3 to 4.
Empty or Full? Empty queue
◦ back = front - 1 Full queue?
◦ the same!◦ Reason: n values to represent n+1 states
Solutions◦ Use a boolean variable to say explicitly whether the
queue is empty or not◦ Make the array of size n+1 and only allow n elements
to be stored◦ Use a counter of the number of elements in the queue
Queue Implementation of Linked List
class Queue {public:
Queue(int size = 10); // constructorbool IsEmpty(void);bool IsFull(void);bool Enqueue(double x);bool Dequeue(double & x);void DisplayQueue(void);
private:int front; // front indexint rear; // rear indexint counter; // number of elementsint maxSize; // size of array queuedouble[] values; // element array
};
Queue Class
Attributes of Queue◦ front/rear: front/rear index◦ counter: number of elements in the queue◦ maxSize: capacity of the queue◦ values: point to an array which stores elements of the queue
Operations of Queue◦IsEmpty: return true if queue is empty, return false
otherwise◦ IsFull: return true if queue is full, return false otherwise◦ Enqueue: add an element to the rear of queue◦ Dequeue: delete the element at the front of queue◦ DisplayQueue: print all the data
Create Queue Queue(int size = 10)
◦ Allocate a queue array of size. By default, size = 10.
◦ front is set to 0, pointing to the first element of the array
◦ rear is set to -1. The queue is empty initially.Queue(int size ) {
values = new double[size];maxSize = size;front = 0;rear = -1;
counter = 0;}
IsEmpty & IsFull
Since we keep track of the number of elements that are actually in the queue: counter, it is easy to check if the queue is empty or full.
Boolean IsEmpty() {if (counter != 0) return false;else return true;
}Boolean IsFull() {
if (counter < maxSize) return false;else return true;
}
Enqueue
boolean Enqueue(double x) {if (IsFull()) {
System.out.println("Error: the queue is full.“);return false;
}else {
// calculate the new rear position (circular)rear = (rear + 1) % maxSize; // insert new itemvalues[rear] = x;// update countercounter++;return true;
}}
Dequeue
double Dequeue() throws EmptyQueueException {if (IsEmpty()) {
System.out.println("Error: the queue is empty.“);throw EmptyQueueException;
}else {
// retrieve the front itemx = values[front];// move front front = (front + 1) % maxSize;// update countercounter--;return x;;
}}
Printing the elements
void DisplayQueue() {System.out.print("front -->“);for (int i = 0; i < counter; i++) {
if (i == 0) System.out.print( "\t”);else System.out.print("\t\t“); System.out.print(values[(front + i) % maxSize]);if (i != counter - 1)
System.out.println();else
System.out.println( "\t<-- rear“);}
}
Using Queue
Create a queue with 5 itemsEnqueue 0,1,2,3,and 4
DisplayQueue();
DequeueDisplayQueue();Enqueue 7;DisplayQueue();
Queue Implementation based on Linked Listclass Queue {
// Data membersNode front; // pointer to front nodeNode rear; // pointer to last nodeint counter; // number of elements
// ConstructorQueue() { // constructor
front = rear = null;counter = 0;
}boolean IsEmpty() {
if (counter != 0) return false;else return true;
}void Enqueue(double x);double Dequeue();void DisplayQueue();
};
Enqueue
void Enqueue(double x) {Node newNode = new Node(x);if (IsEmpty()) {
front = newNode;rear = newNode;
}else {
rear.setNextNode(newNode);rear = newNode;
}counter++;
}
8
rear
rear
newNode
5
58
Dequeuedouble Dequeue() throws EmptyQueueException {
if (IsEmpty()) {System.out.println("Error: the queue is empty.“);throw EmptyQueueException;
}else {
x = front.getData;Node nextNode = front.getNextNode();front = nextNode;counter--;
}}
8
front
5
583
front
Printing all the elements
void DisplayQueue() {System.out.println("front -->“);Node currNode = front;for (int i = 0; i < counter; i++) {
if (i == 0) System.out.print("\t“);else System.out.print("\t\t“); System.out.print(currNode.getData);if (i != counter - 1)
System.out.println();else
System.out.println("\t<-- rear“);currNode = currNode.getNextNode();
}}
Result Queue implemented using linked list will
be never full
based on array based on linked list
Chapter 6: Queues
Specification for a Queue Interface in Java
Chapter 6: Queues
Implementing a Queue Using Java’s LinkedList Can be implemented as an adapter of any
class that implements the List interface◦ ArrayList◦ Vector◦ LinkedList
Removal is O(n) with a linked list◦ O(n) when using ArrayList or Vector
Chapter 6: Queues
Implementing a Queue Using a Circular Array Time efficiency of using a single- or double-
linked list to implement a queue is acceptable◦ However there are some space inefficiencies
Storage space is increased when using a linked list due to references stored at each list node
Array Implementation◦ Insertion at rear of array is constant time◦ Removal from the front is linear time◦ Removal from rear of array is constant time◦ Insertion at the front is linear time
Chapter 6: Queues
Comparing the Three Implementations All three implementations are comparable in
terms of computation time Linked-list implementations require more
storage because of the extra space required for the links◦ Each node for a single-linked list would store a total of
two references◦ Each node for a double-linked list would store a total of
three references A circular array that is filled to capacity would
require half the storage of a single-linked list to store the same number of elements
Chapter 6: Queues
Simulating Waiting Lines Using Queues Simulation is used to study the performance of a
physical system by using a physical, mathematical, or computer model of the system
Simulation allows designers of a new system to estimate the expected performance before building it
Simulation can lead to changes in the design that will improve the expected performance of the new system
Useful when the real system would be too expensive to build or too dangerous to experiment with after its construction
Chapter 6: Queues
Simulating Waiting Lines Using Queues (continued) System designers often use computer
models to simulate physical systems◦ Airline check-in counter for example◦ A special branch of mathematics called queuing
theory has been developed to study such problems
Chapter 6: Queues
Simulate a Strategy for Serving Airline Passengers
Chapter 6: Queues
Simulate a Strategy for Serving Airline Passengers (continued)
Chapter 6: Queues
Simulate a Strategy for Serving Airline Passengers (continued)
Chapter 6: Queues
Simulating Waiting Lines Using Queues (continued)
Chapter 6: Queues
Simulating Waiting Lines Using Queues (continued)
Chapter 6: Queues
Simulating Waiting Lines Using Queues (continued)
Chapter 6: Queues
Simulating Waiting Lines Using Queues (continued)