0% found this document useful (0 votes)
66 views6 pages

05 Stacksandqueues PDF

This document summarizes the differences between abstract data types (ADTs) and data structures. It defines an ADT as a set of behaviors that can be formally specified, such as a stack, while a data structure provides an implementation of an ADT, like using a linked list to implement a stack. Common ADTs include stacks, queues, and sets, while common data structures are arrays, linked lists, trees, and hash tables. The document then discusses using a linked list instead of a static array to implement a stack, providing a more dynamic approach to resource allocation.

Uploaded by

Arpan Rout
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
66 views6 pages

05 Stacksandqueues PDF

This document summarizes the differences between abstract data types (ADTs) and data structures. It defines an ADT as a set of behaviors that can be formally specified, such as a stack, while a data structure provides an implementation of an ADT, like using a linked list to implement a stack. Common ADTs include stacks, queues, and sets, while common data structures are arrays, linked lists, trees, and hash tables. The document then discusses using a linked list instead of a static array to implement a stack, providing a more dynamic approach to resource allocation.

Uploaded by

Arpan Rout
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

' Abstract Data Types

and Data Structures


$' $
Often, these terms are used as synonyms. But it’s better to ADTs and Data Structures
think of them this way:

 An Abstract Data Type (ADT) represents a particular  Some common ADTs that all trained programmers
set of behaviours. know about:

! You can formally define (i.e., using mathematical ! stack, queue, priority queue, dictionary, sequence,
logic) what an ADT is/does. set
e.g., a Stack is a list implements a LIFO policy on  Some common data structures used to implement those
additions/deletions. ADTS:
 A data structure is more concrete. Typically, it is a
! array, linked list, hash table (open, closed, circular
technique or strategy for implementing an ADT.
hashing)
! Use a linked list or an array to implement a stack ! trees (binary search trees, heaps, AVL trees, 2-3
class.
trees, tries, red/black trees, B-trees)

& %& %
 Going one level lower, we get into particulars of
programming languages and libraries We’ll discuss these is some detail.

! Use java.lang.Vector or java.util.Stack or a


C++ library from STL.

' $' $
CS211 — DATA S TRUCTURES A NDADT S 1 CS211 — DATA S TRUCTURES A NDADT S 2

Revisiting the Stack What’s Wrong with this Picture?


Recall our friend the stack, as implemented by an array. There’s something unsatisfying about this implementation.
class stack f
private int maxSize, top = -1;  We have to state, in advance, exactly how many
public static final int DefaultMaxSize = 100; elements we will need.
private Object [] store;
[Or just use the provided default of 100]
public stack () f
maxSize = DefaultMaxSize; ! If we go over that number of elements at any one
store = new Object [maxSize]; point in time, the stack stops working.
g
! If we use a big desiredMaxSize, then we waste
public stack (int desiredMaxSize) f space most of the time.
maxSize = desiredMaxSize; [What if we need several stacks?]
store = new Object [maxSize];
g  This approach uses a static approach to resource
public void push (Object newVal) f allocation:
if (top < maxSize -1) f
top++; ! We have to decide before creating the object what
store[top]=newVal; its size will be.
g else f
! We are not allowed to change the size during its

& %& %
System.err.println ("Sorry, stack is full.");
g lifetime.
g
.
.
 Yes, all resources are ultimately finite. But we would
.
like a little more flexibility and reasonable use of
g
resources.

CS211 — S TACKS A ND Q UEUES 1 CS211 — S TACKS A ND Q UEUES 2


' $' A Linked List Approach
$
me
A Dynamic Approach to
ray
Resource Allocation
d’oh

 What if we could design a stack that used exactly


top
“enough” storage at any given time?

! Sure we will run out of space eventually if we keep  The stack is a set of nodes linked together.
adding elements, but only if we really have to, i.e.,
! Each node has a “value” plus a link variable (a
only if the stack gets really huge.
reference to another node).
! What are the tradeoffs? ! The “value” could be a simple value (e.g., an int),
Are there any disadvantages? a set of values, or a reference to another object
 Dyanamically allocated structures can grow and shrink (e.g., an employee record).
as needed throughout their lifetime.  When you want to push a new value:

 A common yin-yang in CS in static vs. dynamic

& %& %
1. Create a new node via new.
allocation. 2. Set the value of the new node.
3. Set its link field to point to the previous top node.
4. Reset top to point to the new node.

' $' $
CS211 — S TACKS A ND Q UEUES 3 CS211 — S TACKS A ND Q UEUES 4

public interface Stack f


public abstract void push (Object element);
public abstract Object pop ();
public abstract boolean isEmpty ();
public abstract int size (); // Still inside LinkedStack ...
g
public Object pop () f
class Node f Object returnVal;
// Use package-level visibility. if (numElements > 0) f
Object value; returnVal = first.value;
Node next; first = first.next;
numElements--;
public Node (Object value, Node next) f g else f
this.next = next; System.out.println ("Sorry, stack is empty.");
this.value = value; returnVal = null;
g g
g return returnVal;
g
public class LinkedStack implements Stack f
private int numElements; public boolean isEmpty () f
private Node first; return numElements == 0;
g
public LinkedStack () f
numElements = 0; public int size () f
first = null;

& %& %
return numElements;
g g

public void push (Object element) f


Node newNode = new Node (element, first);
first = newNode;
numElements++;
g

CS211 — S TACKS A ND Q UEUES 5 CS211 — S TACKS A ND Q UEUES 6


' $' For completeness, here is the array implementation restated
$
slightly as implementing the Stack interface:
public class ArrayStack implements Stack f
// Still inside LinkedStack ...
private int maxSize;
public static final int DefaultMaxSize = 100;
public static void main (String [] args) f
private int top = -1;
LinkedStack s1 = new LinkedStack();
private Object [] store;
s1.push ("hello");
s1.push ("there");
public ArrayStack () f
s1.push ("world");
maxSize = DefaultMaxSize;
System.out.println ("There are now " + s1.size()
store = new Object [maxSize];
+ " elements.");
g
String s;
s = (String) s1.pop();
public ArrayStack (int desiredMaxSize) f
System.out.println ("Popped: " + s);
maxSize = desiredMaxSize;
s = (String) s1.pop();
store = new Object [maxSize];
System.out.println ("Popped: " + s);
g
s = (String) s1.pop();
System.out.println ("Popped: " + s);
public void push (Object newVal) f
s = (String) s1.pop();
if (top < maxSize -1) f
System.out.println ("Should be empty now.");
top++;
g
store[top]=newVal;
g

& %& %
g else f
System.err.println ("Sorry, stack is full.");
g
g

' $' $
CS211 — S TACKS A ND Q UEUES 7 CS211 — S TACKS A ND Q UEUES 8

// Still inside ArrayStack ...

public Object pop () f


Object ans = null; Array vs. Linked List:
if (top >= 0) f
ans = store[top];
Advantages and Disadvantages
top--;
g else f
System.err.println ("Sorry, stack is empty.");

g
return ans;
g 

public boolean isEmpty () f 


return size() == 0;
g 
public int size () f 
return top + 1;
g

& %& %
g

CS211 — S TACKS A ND Q UEUES 9 CS211 — S TACKS A ND Q UEUES 10


' Another Strategy:
Split the Difference
$' $
topChunk

0 1 2 N-1 “Splitting the Difference”: Advantages


d’oh ray me ... la 0 1 2 N-1 and Disadvantages
tea doe ?? ... ??

top 


 Keep a linked list of arrays (NodeChunks):

! Each NodeChunk has a reference to the one before
it. 
! Keep a reference to the “top chunk”, plus a top

integer that points to the top element in the top

& %& %
chunk.

 Must decide on a good chunk size somehow.

! Constructor arg and/or use a default size.

' $' $
CS211 — S TACKS A ND Q UEUES 11 CS211 — S TACKS A ND Q UEUES 12

Another ADT: The Queue Implementing a Queue


with an Array
 A queue is a list that implements a FIFO (First In is the first
last
First Out) policy on insertions and deletions.
0 1 2 3 4 N-2 N-1
! Can add elements only to the end of the list.
?? ray me far ?? ... ?? ??
! Can remove elements only from the front of the list.

 “Add” is called enter, enqueue, or add


first last
 “Delete” is called leave, dequeue, or remove
An ArrayQueue is trickier than an ArrayStack:
 Misc. extra methods: isEmpty, size

! There are two pointers (int indexes into array) to keep


public interface Queue f
public abstract void enter (Object element); track of.
public abstract Object leave ();
public abstract boolean isEmpty (); ! When you run out of room, start over at the beginning.

& %& %
public abstract int size ();
g ! Of course, this static approach means you are limited to
at most N elements in your queue at any given moment.

CS211 — S TACKS A ND Q UEUES 13 CS211 — S TACKS A ND Q UEUES 14


' Implementing a Queue
with an Array
$' $
first class ArrayQueue implements Queue f
private int first=0, last=-1;
N-1 0
N-2 1
private final int DefaultMaxSize = 100;
?? ?? last private int maxSize, numElements = 0;
?? ray
2 private Object [] store;
...
me

far
3 public ArrayQueue () f
this.maxSize = DefaultMaxSize;
4
?? store = new Object[maxSize];
g
...

public ArrayQueue (int maxSize) f


this.maxSize = maxSize;
store = new Object[maxSize];
g

Think of the array as a circle. public void enter (Object newElt) f


if (size() < maxSize) f
! Use modular arithmetic to stay in the valid range of last = (last + 1) % maxSize;
store[last] = newElt;
indexes. To increment last on an enter: numElements++;
last = (last + 1) % N; g else f

& %& %
System.err.println ("Sorry, queue is full.");
g
[Assumes there is space, i.e., element 0 is empty]
g
! Items in the range first ... last are full.

! Items in the range last+1 ... first-1 are empty.

' $' $
CS211 — S TACKS A ND Q UEUES 15 CS211 — S TACKS A ND Q UEUES 16

public Object leave () f public static void main (String[] args) f


if (size() > 0) f ArrayQueue q1 = new ArrayQueue(5);
Object ans = store[first]; q1.enter ("do");
first = (first + 1) % maxSize; q1.enter ("re");
numElements--; q1.enter ("mi");
return ans; q1.enter ("fa");
g else f q1.enter ("so");
System.err.println ("Sorry, queue is empty."); q1.print();
return null; System.out.println ("Queue should be full now.");
g q1.enter ("la");
g System.out.println ("Removed " + q1.leave());
System.out.println ("Removed " + q1.leave());
public void print () f System.out.println ("Removed " + q1.leave());
System.out.println("Printing the queue: " System.out.println ("Removed " + q1.leave());
+ size() + " elements."); System.out.println ("Removed " + q1.leave());
int j = first; System.out.println ("Removed " + q1.leave());
for (int i=0; i< size(); i++) f q1.print();
System.out.println (store[j]); q1.enter ("la");
j = (j + 1)%maxSize; q1.enter ("ti");
g q1.print();
g q1.enter ("doh");
q1.enter ("ray");
public int size () f q1.enter ("me");
return numElements; q1.print();

& %& %
g q1.enter ("far");
q1.enter ("sew");
public boolean isEmpty () f q1.print();
return size() == 0; System.out.println ("Removed " + q1.leave());
g g
g

CS211 — S TACKS A ND Q UEUES 17 CS211 — S TACKS A ND Q UEUES 18


' Implementing a Queue
$' public class LinkedQueue implements Queue {
private int numElements=0;
private Node first=null, last=null;
$
as a Linked List
public void enter (Object element) {
Node newNode = new Node (element, null);
d’oh if (numElements == 0) {
ray first = newNode;
} else {
me last.next = newNode;
}
last = newNode;
numElements++;
first }

last public Object leave () {


Object returnVal;
if (numElements > 0) {
 Pretty straightforward to implement. returnVal = first.value;
first = first.next;
numElements--;
 Only caveat: watch out on enter
} else {
System.out.println ("Sorry, queue is empty.");
! If queue empty, adjust first to point to new node. returnVal = null;

& %& %
}
! Otherwise reset last.next to new node.
return returnVal;
}
 Can also implement using a NodeChunk
[Each NodeChunk contains an array of values.] // Obvious definitions for isEmpty and size omitted.
}

' $' $
CS211 — S TACKS A ND Q UEUES 19 CS211 — S TACKS A ND Q UEUES 20

This program:
class FigureQueueTest {
public static void main (String[] args) {
Queue q = new LinkedQueue();
Circle c1, c2;
Misc. Notes c1 = new Circle();
c1.setSize(50);
c1.setLoc(25,30);
 We have decided to declare the Node fields value and c2 = new Circle();
Square s1 = new Square();
next as package-level visible. s1.setSize (75);
q.enter(c1);
! This means that other classes in the same package, q.enter(c2);
q.enter(s1);
such as LinkedQueue, can directly manipulate the
while (!q.isEmpty()) {
instance variables of each Node instance. Figure f = (Figure) q.leave();
f.draw();
 Also, we can use more interesting objects than Strings }
and Integers in our stacks and queues. }
}

! Could have a list of Figures or EmployeeRecords


Produces this output:

& %& %
Circle at x = 25 y = 30 with radius = 50
Circle at x = 0 y = 0 with radius = 0
Square at x = 0 y = 0 with width = 75 and height = 75

CS211 — S TACKS A ND Q UEUES 21 CS211 — S TACKS A ND Q UEUES 22

You might also like