350 likes | 630 Views
top. F E D C B A. Stacks. Stack : restricted variant of list elements may by inserted or deleted from only one end : LIFO lists top : the accessible end of the list operations: “ push ”, “ pop ” many applications easy to implement: arrays linked lists. Array Implementation.
E N D
top F E D C B A Stacks • Stack: restricted variant of list • elements may by inserted or deleted from only one end : LIFO lists • top: the accessible end of the list • operations: “push”, “pop” • many applications • easy to implement: • arrays • linked lists stacks, queues
Array Implementation • A simplified version of list implementation • array of fixed size • top: always the first element • current is always the top element • push: insert at top ! • pop: remove from top ! stacks, queues
Stack ADT interface Stack { public void clear( ) //remove all ELEM's public void push(Object it) //push ELEM onto stack public Object pop( ) // pop ELEM from top public Object topValue( ) // value of top ELEM public bool isEmpty( ) // TRUE if stack is empty } stacks, queues
size size top class AStack implements Stack { // Array based stack class private static final int defaultSize = 10; private int size; // Maximum size of stack private int top; // Index for top Object private Object [] listarray; // Array holding stack AStack() { setup(defaultSize); } AStack(int sz) { setup(sz); } private void setup(int sz) { size = sz; top = 0; listarray = new Object[sz]; } public void clear() { top = 0; } // Clear all Objects public void push(Object it) // Push onto stack { Assert.notFalse(top < size, "Stack overflow"); listarray[top++] = it; } public Object pop() // Pop Object from top { Assert.notFalse(!isEmpty(), "Empty stack"); return listarray[--top]; } public Object topValue() // Return top Object { Assert.notFalse(!isEmpty(), "Empty stack"); return listarray[top-1]; } public boolean isEmpty() { return top == 0; } } stacks, queues
top Dynamic Memory Implementation • Simplified version of the linked list implementation • the head and tail pointers of the list implementation are not used stacks, queues
class LStack implements Stack { // Linked stack class private Link top; // Pointer to list header public LStack() { setup(); } // Constructor private void setup() // Initialize stack { top = null; } // Create header node public void clear() { top = null; } // Clear stack public void push(Object it) // Push Object onto stack { top = new Link(it, top); } public Object pop() { // Pop Object from top Assert.notFalse(!isEmpty(), "Empty stack"); Object it = top.element(); top = top.next(); return it; } public Object topValue() // Get value of top Object { Assert.notFalse(!isEmpty(), "No top value"); return top.element(); } public boolean isEmpty() // True if stack is empty { return top == null; } }// Linked stack class stacks, queues
- - wrong - Applications • Checking mathematical expressions • Equal number of left/right (, {, [, ), }, ] stacks, queues
Algorithm • Read the expression from left to right • p: next symbol in expression • Repeat until (empty(stack) ) { read(p); if p = ( or { or [then push(stack,p); loop; if p = ) or } or ] then c = pop(stack); if c != p then error!! } if (not empty(stack) ) then error!! stacks, queues
[ ( ( ( ( stacks, queues
More Applications • Evaluation of arithmetic expressions: • convert infix to postfix or prefix • evaluate postfix or prefix expression • infix, prefix, postfix: refer to the relative position of the operator with respect to the operands • infix : A+B • prefix : +AB • postfix : AB+ stacks, queues
Infix to Postfix or Prefix • Read from left to right • First convert operations of higher precedence • parenthesis have the highest precedence • “^” have precedence over • “*”, “/” have the same precedence but higher than • “+”, “-” which all have the same precedence • The converted prefix or postfix part is treated as a single operand • If all operators have the same precedence then convert from left to right stacks, queues
Infix to Postfix or Prefix • A+B*C : ‘*’ > ‘+’ A+(B*C) : equivalent Α+(ΒC*) : B*C topostfix ABC*+ : postfix • (A+B)*C : (…) > ‘*’ (AB+)*C : A+B topostfix (AB+)C* : (AB+)*C topostfix AB+C* : postfix • Postfix and Prefix have no parenthesis !! stacks, queues
Infix to Postfix or Prefix • A+B-C : ΑΒ+C- postfix (A+B)*(C-D) : AB+CD-* Α$Β*C-D+E/F/(G+H) : AB$C*D-EF/GH+/+ A-B/(C*D$E) : ABCDE$*/- • A+B-C : -+ABC prefix (A+B)*(C-D) : *+AB-CD A$B*C-D+E/F/(G+H) : +-*$ABCD//EF+GH A-B/(C*D$E) : -A/B*C$DE stacks, queues
Convert infix to postfix • Read expression from left to right • output operands • push operators to stack • higher precedence operators must be above lower precedence operators • before pushing an operator into the stack check the precedence of operators already in the stack • if operator in stack has higher precedence output this operator and then insert the current operator in the stack • “(”, “[”, “{”have higher precedence, push in stack • if “)”, “]”, “}” pop stack until “(”, “[”, “{” is found • don’t output “(”, “[”, “{”, “)”, “]”, “}” stacks, queues
Infix to Postfix Example • (A + B)*C • push “(” in stack • output A • push “+” in stack • output B • don’t push “)”, pop all operators • output “+”, ignore “(”, “)” • “*” push in stack • output C • output “+” stacks, queues
Symbol ( A + B ) * C Postfix A A AB AB+ AB+ AB+C AB+C* Stack ( ( (+ (+ * * Example: (A + B)*C stacks, queues
stack = NULL; while (not end of input) { symbol = read next symbol; if (symbol == operand) output(symbol); else { while(!empty(stack) && (preced (stack(top)) > preced(symbol)) {top symbol = pop(stack); output(top symbol); } push(stack, symbol); } } while not_empty(stack) { top symbol = pop(stack); output(top symbol); } Algorithm stacks, queues
Evaluation of Postfix While (not end of expression) { read symbols from left to right; result = 0 if (symbol == operand) push (stack); else { operand1 = pop(stack); operand2 = pop(stack); result = operand1 operator operand2; push(stack, result); } } result = pop(stack); stacks, queues
Postfix: 6 2 3 + - 3 8 2 / + * 2 $ 3 + Symbol 6 2 3 + - 3 8 2 / + * 2 $ 3 + Operand1 2 6 6 6 6 8 3 1 1 7 7 49 Operand2 3 5 5 5 5 2 4 7 7 2 2 3 Value 5 1 1 1 1 4 7 7 7 49 49 52 stack Operand 6 6,2 6,2,3 6,5 1 1,3 1,3,8 1,3,8,2 1,3,4 1,7 7 7,2 49 49,3 52 stacks, queues
Queue • Queue elements may only be inserted at the rear and removed from the front • restricted form of list • FIFO: first in first out • insert: enqueue operation • remove: dequeue operator stacks, queues
rear front enqueue (queue, D) A B C dequeue (queue) A B C D B C D stacks, queues
4 3 2 1 0 x x Array Implementation • If the elements are the first n elements of array and the front element is at position 0 • enqueue requires Θ(1)operations but, • dequeue requires Θ(n) operations (all elements must be shifted) • Condition of empty queue? stacks, queues
4 3 2 1 0 4 3 2 1 0 A Condition of empty queue:rear = front Initial values: rear = front = LIST_SIZE - 1 front points to the position proceeding the first element front = 4 rear = 4 front = 4 rear = 0 input A stacks, queues
4 3 2 1 0 C B Α 4 3 2 1 0 D C B Α 4 3 2 1 0 E D C B Α front = 4 rear = 2 front = 4 rear = 3 The condition of empty queue is true but the queue is not empty “E” cannot be inserted: The last array positionmust be left empty front = 4 rear = 4 stacks, queues
Insert “E”, “F” Circular list Delete“Α” 4 3 2 1 0 E D front = 2 rear = 0 front = 0 rear = 3 C F 4 3 2 1 0 4 3 2 1 0 D D Delete“B” C C B B Α front = 1 rear = 3 stacks, queues
Queue ADT public interface Queue { // Queue ADT public void clear(); // Remove all Objects from queue public void enqueue(Object it); // Enqueue Object at rear of queue public Object dequeue(); // Dequeue Object from front of queue public Object firstValue(); // Return value of top Object public boolean isEmpty(); // Return TRUE if stack is empty } stacks, queues
size front size rear class AQueue implements Queue { // Array-based queue class private static final int defaultSize = 10; private int size; // Maximum size of queue private int front; // Index prior to front item private int rear; // Index of rear item private Object [] listArray; // Array holding Objects AQueue() { setup(defaultSize); } // Constructor: default size AQueue(int sz) { setup(sz); } // Constructor: set size void setup(int sz) // Initialize queue { size = sz+1; front = rear = 0; listArray = new Object[sz+1]; } public void clear() // Remove all Objects from queue { front = rear = 0; } stacks, queues
public void enqueue(Object it) { // Enqueue Object at rear Assert.notFalse(((rear+1) % size) != front, "Queue is full"); rear = (rear+1) % size; // Increment rear (in circle) listArray[rear] = it; } public Object dequeue() { // Dequeue Object from front Assert.notFalse(!isEmpty(), "Queue is empty"); front = (front+1) % size; // Increment front return listArray[front]; // Return value } public Object firstValue() { // Return value of front Object Assert.notFalse(!isEmpty(), "Queue is empty"); return listArray[(front+1) % size]; } public boolean isEmpty() // Return true if queue is empty { return front == rear; } }// class AQueue stacks, queues
front rear Dynamic Memory Implementation • Simple adaptation of the linked list implementation • current always points to the first element • the head pointer of the list implementation is not used stacks, queues
class LQueue implements Queue { // Linked queue class private Link front; // Pointer to front node private Link rear; // Pointer to rear node public LQueue() { setup(); } // Constructor public LQueue(int sz) { setup(); } // Constuctor: Ignore sz private void setup() // Initialize queue { front = rear = null; } // Remove all Objects from queue public void clear() { front = rear = null; } public void enqueue(Object it) { // Enqueue Object at rear of queue if (rear != null) { // Queue not empty: add to end rear.setNext(new Link(it, null)); rear = rear.next(); } else front = rear = new Link(it, null); // Empty queue } stacks, queues
public Object dequeue() { // Dequeue Object from front Assert.notFalse(!isEmpty()); // Must be something to dequeue Object it = front.element(); // Store dequeued Object front = front.next(); // Advance front if (front == null) rear = null; // Dequeued last Object return it; // Return Object } public Object firstValue() // Return value of top Object { Assert.notFalse(!isEmpty()); return front.element(); } public boolean isEmpty() // Return true if queue is empty { return front == null; } }// classes LQueue stacks, queues
Priority Queue • Ascending: elements in any order but dequeue removes the minimum • Descending: dequeue removes the maximum stacks, queues
5 4 3 2 1 Ε front = 5 rear = 4 D G Α ascending descending 5 4 3 2 1 5 4 3 2 1 Ε Ε front = 5 rear = 4 front = 5 rear = 4 D D G ? Α Example: Dequeue stacks, queues
5 4 3 2 1 5 4 3 2 1 Ε E D D G Α Α 5 4 3 2 1 5 4 3 2 1 G Ε E D D Α Α Array Implementation • Problem: dequeue creates empty slots • Solution(1): move elements: Θ(n) operations on dequeue • Solution(2): store elements in ascending (descending) order: Θ(n) operations on enqueue stacks, queues