1 / 23 cop 3540 data structures with oop chapter 4 stacks and queues

22
1/ 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

Upload: roderick-carr

Post on 11-Jan-2016

213 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

1 / 23

COP 3540 Data Structures with OOP

Chapter 4Stacks and Queues

Page 2: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

2 / 23

A Different Kind of Structure

Stacks, queues, and priority queues – different kinds of storage structures.

Different data structures have different sets of problems that they are most suited to representing.

Consider Arrays – as a data storage structure: very useful. easy to insert into, delete from, and search for

specific items.

Page 3: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

3 / 23

Access (interface) Arrays: theoretically, access is immediate via index

or by searching through cells sequentially. If ordered, can access more quickly via binary

search Only one item can be accessed. ‘That’ is the interface.’

In abstract data structures (stacks, queues, trees, priority queues), real access (that is, how do we get to it…) is: defined a bit differently and is controlled by an interface that is normally not

visible to the user.

Page 4: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

4 / 23

Stacks Stacks - access to only one item at a time. Think of a stack of dishes. It is a LIFO data structure.

Extremely useful tool in programming: Evaluate parenthesized expressions, Evaluate arithmetic expressions even with lots

of parentheses, Traversing binary trees, Searching vertices of a graph, and much more.

Consider stacked-based architecture and calling sequences / return addresses….

Page 5: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

5 / 23

Stacks Stacks are conceptual (logical), abstract structures.

We can envision them. Really no such thing as a real stack! But we are interested in how we can implement the

logical structure on a machine.

Basic operations – four. Know these!: Push (onto top of stack) Pop (top item off of stack) Stack overflow (stack full) – cannot push!

• (normally error condition or special processing needed. Same for underflow…)

Stack underflow (stack empty) – cannot pop!

Let’s look at Java Code for a Stack

Page 6: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

6 / 23

class StackApp{ public static void main(String[] args) { StackX theStack = new StackX(10); // makes new stack of size 10.

//note: argument sent to the Stack object for use by constructor// note: we DO NOT KNOW how the stack actually looks!!!!!// that is, we do NOT know what the underlying data structure looks like!!!!!

theStack.push(20); // push items onto stack theStack.push(40); // These are ‘logical’ operations!!! theStack.push(60); (How to evaluate??) theStack.push(80);

while( !theStack.isEmpty() ) // until it's empty, delete item from stack { long value = theStack.pop(); // what is author doing here??? System.out.print(value); // display it System.out.print(" "); } // end while

System.out.println(""); } // end main()} // end class StackApp

Page 7: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

7 / 23

// stack.java demonstrates stacks Note: I have taken liberties with the ‘{‘ to fit this code on one page.class StackX { private int maxSize; // size of stack array private long[] stackArray; // recall: ‘instance variables’ private int top; // top of stack//-------------------------------------------------------------- public StackX(int s) // constructor // (How can you tell this is the Constructor??) { // ONLY NOW CAN WE SEE STACK IS IMPLEMENTED AS AN ARRAY ! maxSize = s; // set array size // Recall: ‘ local variables’ Where are they known?? stackArray = new long[maxSize]; // Create array; ARRAY IS OF ‘LONGS’

//’long’ is a primitive data structure; how longs are implemented and // accessed are defined in system. No need for separate class for this. top = -1; // no items yet } // end StackX() DISCUSS//-------------------------------------------------------------- public void push(long j) { // put item on top of stack stackArray[++top] = j; // increment top, insert item // tell me exactly how this works!! } // end push() // How many operators do you see?//-------------------------------------------------------------- public long pop() { // take item from top of stack return stackArray[top--]; // access item, decrement top // tell me exactly how this works!! }// end pop () //recall: What is the ‘other kind’ of variable?????//-------------------------------------------------------------- public long peek() { // peek at top of stack return stackArray[top]; // when we come into this object, the pointer is } // end peek() // pointing to the topmost element.//-------------------------------------------------------------- public boolean isEmpty() { // true if stack is empty return (top == -1); // tell me exactly how this works!! } // end isEmpty()//-------------------------------------------------------------- public boolean isFull() { // true if stack is full //Ah ha! We see (above) that the Stack is ‘implemented’ as return (top == maxSize-1); // an array! But it doesn’t have to be!!!!! }} // end class StackX // Storage structure transparent to client. Good!!! Why???

Page 8: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

8 / 23

Notes:

Always check to see if there are items on the stack before popping the stack or if there is room before pushing the stack isFull? isEmpty? Appropriate error routines are up to the developer / user

Best approach: in Push() and Pop(), check for isEmpty and isFull within these methods. Regardless, they need to be specified.

Go through Reversing a Word routine in book. We will look at Delimiter Matching.

Page 9: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

9 / 23

Delimiter Matching

Stacks are used a lot to temporarily store tokens like a char or parts of arithmetic expressions having parentheses in them and later retrieve them when we have a number of delimiters.

‘Delimiters’ = normally special characters (e.g. commas, white space, braces, brackets, parentheses, …)

They normally set something off or bracket something.

Delimiters (but not white spaces) must always ‘balance’ – the first right parenthesis balances the ‘most recent’ unbalanced left parenthesis, etc.

Page 10: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

10/ 23

Delimiter Matching – more

Consider: x = (a+b*(c/d**4-e/(2*a)-5)-14.2/g);

How do you and the machine evaluate this? (You will see this again.)

You absolutely need to know the order of evaluation of most common operators.

Note: this ‘order of evaluation’ (operator precedence) is basic to all programming languages!!

Page 11: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

11/ 23

Delimiters – the Algorithm Algorithm: tries to evaluate as it goes. But when it encounters an opening delimiter, it must process it

and may push a token onto a stack only to pop it later.

When the algorithm encounters closing delimiter or operator of lesser precedence), the algorithm may pop the stack and perform the evaluation thus creating a temporary (or partial) value, May push temporary result ‘back’ onto stack if more terms follow.

If no closing delimiter is found (or if unbalanced), syntax error! For pairs of delimiters, such as ‘parentheses’ the one opened last

closed first.

If different delimiters are used (brackets, parentheses, etc.) then the correct delimiter must be found, if syntax of the expression is valid.

Different delimiters? Parentheses; brackets for indexes … If syntax is invalid, compilation error!

Let’s look at some code.

Page 12: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

12/ 23

// brackets.java // Discuss: stack for handling string input / evaluations…import java.io.*; // for I/O // Discuss each method briefly.class StackX { private int maxSize; //Here’s my ‘instance’ data, right? private char[] stackArray; //declares a pointer (reference), stackArray, to a char array private int top; // where the array itself is not yet allocated / built.//-------------------------------------------------------------- public StackX(int s) // constructor { // when object of class StackX is created in its client, maxSize = s; // BracketChecker, size of the stack is passed to this Constructor stackArray = new char[maxSize]; // Constructor uses this parameter to determine size of array object. top = -1; // Stack object, just created, is empty, so top of stack is set to -1, an invalid array reference. } // end StackX()//--------------------------------------------------------------

public void push(char j) // put item on top of stack no change { stackArray[++top] = j; // Exactly how does this work for first item? Values of top? }//end push()//-------------------------------------------------------------- public char pop() // take item from top of stack { return stackArray[top--]; // Note top is decremented AFTER item is popped! } // end pop()//--------------------------------------------------------------

public char peek() { // peek at top of stack // note: encapsulation; see stack and // methods that process

. return stackArray[top]; } // end peek()//-------------------------------------------------------------- public boolean isEmpty // cut off for space…

Page 13: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

13/ 23

class BracketChecker { private String input; // input string public BracketChecker(String in) // constructor; When object is created, a String is { input = in; } // passed to it. Becomes value of ‘input.’//-------------------------------------------------------------- public void check() { int stackSize = input.length(); // get max stack size. Where does input.length() come from? StackX theStack = new StackX(stackSize); // make stack Creates stack object of size stackSize. Do you see???

// Stack (array) is declared to be the size of input string. for(int j=0; j<input.length(); j++) { // Get chars in turn char ch = input.charAt(j); // get a char Where does input.charAt(j) come from? switch(ch) { case '{': // opening symbols case '[': // ROUTINE IS ONLY CHECKING FOR BALANCING DELIMITERS. IS NOT EVAL… case '(': theStack.push(ch); // push the symbol onto the Stack. Check it out. break; case '}': // closing symbols case ']': case ')': if( !theStack.isEmpty() ) // if stack not empty and came in with ‘closing’ delimiter… {

char chx = theStack.pop(); // pop and check if( (ch=='}' && chx!='{') || ch==']' && chx!='[') || (ch==')' && chx!='(') ) System.out.println("Error: "+ch+" at "+j); } else // prematurely empty System.out.println("Error: "+ch+" at "+j); break; default: // no action on other characters. Routine is only looking for delimiters; not evaluating; checking!! break; } // end switch } // end for // at this point, all characters have been processed if( !theStack.isEmpty() ) System.out.println("Error: missing right delimiter"); } // end check() } // end class BracketChecker

Page 14: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

14/ 23

class BracketsApp { public static void main(String[] args) throws IOException { String input; while(true) //Notice indentation and scope terminators. { System.out.print ( "Enter string containing delimiters: ");

input = getString(); // read a string from keyboard Note the static method in Main if( input.equals("") ) // quit if [Enter] break // otherwise, make a BracketChecker

BracketChecker theChecker = new BracketChecker(input);// OK. Now, this creates an object of type BracketChecker. Object name is

theChecker.// Pass the string, ‘input’ to the Constructor.

theChecker.check(); // calls check() within theChecker. } // end while // the check() method } // end main()//-------------------------------------------------------------- public static String getString() throws IOException { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String s = br.readLine(); return s; } // end getString() //-------------------------------------------------------------- } // end class BracketsApp // note the DESIGN! Note how all of these objects have their // responsibilities and how they collaborate to provide the needed functionality; reusability too.

Page 15: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

15/ 23

Stack as a Conceptual Aid

The notion (vision) of a stack is simple. Once a Stack (very reusable) is set up, you don’t

have to keep track of indices But there is limited access to the stack elements

via push() and pop()

Efficiency: Push() and pop() take O(1) time – a constant. Why?? No dependency on number of items in stack. No comparisons or moves necessary. For many applications, this is a very convenient logical

data structure.

Page 16: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

16/ 23

Queues A FIFO data structure; is a ‘line.’ A Stack is a LIFO data structure. What is a FISH data structure?

A queue another conceptual data structure (logical data structure) can be implemented using an array, linked list or other structure.

Queues: VERY useful for many different applications. Typically used to model waiting lines, such as planes waiting to

take off; waiting lines at McDonalds, etc. and much more! Many queues in your operating system:

• Print queues• Job queues• Ready queues• Keyboard queues – data not lost; just ‘queued up.’

Page 17: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

17/ 23

Queues - terminology

Queues data entered in one end Data extracted from the other end, as envisioned.

Thus, our queue operations are insert() and remove()

• insert() at the rear (back or tail) of the queue• remove() at the front (head) of the queue.

These are reasonably common terms. Rear of queue is the tail (back or tail or end) Front of queue is head. We will use: insert, remove, front and rear.

Page 18: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

18/ 23

Queues – more Potential error conditions

Attempt to remove an item from an empty queue??

• Want ‘empty queue’ message returned. Attempt to insert an item into a ‘full queue’

• Want full queue message returned.

As in a Stack, we must ‘create’ the Queue.

Can also have Circular Queues: extremely useful! Must be careful to keep track of the front and rear of the

queue so that they do not wrap!

Consider: Java code for a Queue.

Page 19: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

19/ 23

class QueueApp { public static void main(String[] args) { Queue theQueue = new Queue(5); // queue holds 5 items; Creates Queue theQueue and

// passes a 5 as argument to theQueue’s Constructor. theQueue.insert(10); // insert 4 items theQueue.insert(20); theQueue.insert(30); theQueue.insert(40);

theQueue.remove(); // remove 3 items theQueue.remove(); // (10, 20, 30) theQueue.remove();

theQueue.insert(50); // insert 4 more items theQueue.insert(60); // (wraps around) theQueue.insert(70); theQueue.insert(80);

while( !theQueue.isEmpty() ) // remove and display all items. { long n = theQueue.remove(); // (40, 50, 60, 70, 80) System.out.print(n); System.out.print(" "); } // end while() System.out.println(""); } // end main() } // end class QueueApp////////////////////////////////////////////////////////////////

Page 20: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

20/ 23

// Queue.javaclass Queue { // Please note my moving of ‘{‘ and a few other things to poor spots – in the interest of space... private int maxSize; private long[] queArray; // reference to an array of ‘longs.’ private int front, rear, nItems; public Queue (int s) { // constructor Note: size and structure of queue determined here. User does not maxSize = s; // see (or care) how queue is implemented. (See: array here. queArray = new long[maxSize]; Note: Constructor is passed desired queue size from client. front = 0; Note: See instance and local variables?? rear = -1; Note: Here’s the queue; implemented as an array; front and rear nItems = 0; and number of Items setup and initialized. } // end Constructor public void insert(long j) { // put item at rear of queue if(rear == maxSize-1) // deals with wraparound //Note: insert() FIRST checks to see if there’s room for an insert. rear = -1; If rear is at maxSize-1, then we need to wrap to 0. queArray[++rear] = j; // increment rear and insert So rear is set to -1 and it is set to 0 in this statement. nItems++; // one more item // note: number of items in queue is incremented. } // end insert() public long remove() { // take item from front of queue long temp = queArray[front++]; // get value and increments front //Note: creates a temp variable, temp, and moves if (front == maxSize) // deal with wraparound // the queue item into it and increments front pointer. front = 0; // it then checks to see if the new value causes wrap. nItems--; // one less item // Lastly, it decrements the queue size; returns temp. return temp; } // end remove() public long peekFront() { // peek at front of queue return queArray[front]; } // end peek()

public boolean isEmpty() { // true if queue is empty // Do you see a problem with insert() ? return (nItems==0); } // end isEmpty() public boolean isFull() { // true if queue is full return (nItems==maxSize); } // end isFull() public int size() // number of items in queue return nItems; } // end size() } // end class Queue

Page 21: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

21/ 23

Efficiency of Queues

insert() and remove() are considered O(1) times; that is, a constant. (immediate!)

Always know the value of the appropriate index

Simply a matter of ‘inserting’ or ‘removing’ at that point. Just about simply inserting or removing and

• a minor change in value of front or rear • (unless we wrap).

Deques A double-ended queue Can insert() and delete() from either end.

• Can insertLeft() and insertRight(), etc. Know it is there and is quite useful and versatile. Look for it

if you need it.

Page 22: 1 / 23 COP 3540 Data Structures with OOP Chapter 4 Stacks and Queues

22/ 23

Questions?