Data Structures and Algorithms Week8: Stacks, Queues and Graphs
Stacks and Queues
Content
- Stacks
- Abstract data types
- Queues
- Priority queues
- Stacks and queues in the Java collections framework
Stacks
- A stack is an object that contains a list of elements, like an ArrayList.
- However the methods of a stack allow us to add elements only to the top of the list, and to remove only the element that is at the top of the list.

- 4 operations on stack

Stack feature:Last in first out
- A Stack is a “Last In First Out” (LIFO) structure.
- Real world examples
- A stack of plates waiting to be washed
- A stack of cards in a patience game (see practical instructions).
- Other Games such as Connect 4, Towers of Hanoi, etc.
- Many examples in computer science – e.g. stack of method calls.

Implementing a stack using an Arraylist
public class StringStack { private ArrayList<String> list = new ArrayList<String>(); public void push(String s) { list.add(s); } public String pop() { assert list.size() != 0; return list.remove(list.size()-1); } public String peek() { assert list.size() != 0; return list.get(list.size()-1); } public boolean isEmpty() { return list.isEmpty(); }}What did we do
- We took an ArrayList, which has more than 25 methods, and used it to create a StringStack, that can perform only 4.
- Everything we can do with a StringStack we can also do with an ArrayList.
- There are many things we can do with an ArrayList but cannot do with the StringStack.
- So what was the point of the stack? Is it wasteful?
Why would we do that
- There are many cases in which we want to treat data as being on a stack.
- In these cases there are advantages in hiding all methods except those that treat the data as being on a stack.
- It makes the program easier to understand, reason about, and modify.
- It means that we can replace one implementation of a stack with another.
A better way to describe the procedure of program
Abstraction
- In computer science Abstraction is the hiding of irrelevant detail.
- The fact that our StringStack uses an ArrayList to store data is irrelevant. We do not need to know that the stack is implemented in this way, and we do not want anyone to write code that is dependent on that particular implementation.
Hiding is better than showing more detail for you to worry about
Abstract data types
- A stack is an example of an Abstract Data Type (ADT).
- An ADT is defined by a set of operations that can be performed on its data.
- The ADT hides all details of how those operations are implemented, and how data are stored.
- The operations that can be performed ADT define an interface to the ADT.
Stack exercise
- If s is an initially empty stack
- state the values of the variables a and b after the following code fragment is run:
s.push("Red");s.push("Orange");s.push("Blue");s.pop();s.push("Yellow");s.pop();String a = s.pop();s.push("Brown");s.pop();String b = s.pop();Queues
- A queue is an ADT which maintains a list of data
- The methods available allow us to add data only to the back of the queue, and to remove data only from the front of the queue.
- A queue is FIFO (First In First Out) structure
- 4 operations on queue

Implementing a queue using an Arraylist
public class StringQueue { private ArrayList<String> list = new ArrayList<String>(); public void add(String s) { list.add(s); } public String remove() { assert list.size() != 0; return list.remove(0); } public String peek() { assert list.size() != 0; return list.get(0); } public boolean isEmpty() { return list.isEmpty(); }}Queue Exercise
- If the q refers to a queue that is initially empty
- state the values of the variables a and b after the following code fragment is run
q.add("Diamond");q.add("Tobby");q.remove();q.add("Garnet");q.add("Emeric");q.remove();String a = q.remove();q.add("Sapphire");String b = q.remove();Priority queues
- A priority queue implements the same methods as an ordinary queue, but it works in BIFO (Best In First Out) manner.
- Each element in the queue is allocated a priority, and the
remove()method always removes the element with the highest priority.
- For example suppose that a priority queue contains Strings, and that when two Strings are compared the one that is lowest in alphabetical order has highest priority.
- The code
pq.add("Jam");pq.add("Ham");pq.add("Spam");String best = pq.remove();Results in best pointing to the String “Ham”.
Implementing a priority queue
- A simple implementation would use an ArrayList and would be like the queue implementation shown earlier except that the add method is implemented as follows:
public void add(String s) { int i = 0; int size = list.size(); while (i < size && s.compareTo(list.get(i)) > 0) { i++; } list.add(i, s);}
The add method would be O(n)
A more efficient implementation uses a data structure known as a heap (not the same as the heap). The add method is then O(log n)
We shall not cover heaps in this module.
Double-ended queue (DEQUE)
- A deque (pronounced “deck”) is like a queue, except that elements can be added or removed from either end.

Stacks and queues in the java collections framework
- The Java collections framework contains an interface
Queue, which extends theCollectioninterface. - The
Queueinterface contains the methods that we have already mentioned when describing queues, plus a few others. - For example in addition to the
remove()method, there is anpoll()method. The difference between the two is that, if the queue is empty,remove()throws an exception whereaspoll()returns anullvalue.
- Similarly the
Queueinterface providesadd()andoffer()methods, the difference being thatadd()has avoidreturn type and throws an exception if the capacity of the queue is exceeded, whereasofferreturns a Boolean value – false if the capacity was exceeded, and true otherwise. - The
Queueinterface is implemented by, among others, theLinkedListandArrayDequeclasses
- The Java collections framework does not contain a
Stackinterface. There is aStackclass, but its use is not advised. It is better to use theArrayDequeclass - There is a class
PriorityQueuethat implements theQueueinterface and where theremove(),poll(), andpeek()methods return the highest-priority element.
Simplified summary of some java collections framework classes
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque‹E>, Cloneable, Serializable { transient int size; transient LinkedList.Node<E> first; transient LinkedList.Node<E> last; private static final long serialVersionUID = 876323262645176354L; public LinkedList() { this.size = 0; } public LinkedList(@NotNull @Flow(sourcelsContainer = true, targetsContainer = true) Collection<? extends E> c) { this(); this.addAll(c);}Summary
- A stack is a LIFO (Last-In, First-Out) structure.
- A queue is a FIFO (First-In, First-Out) structure.
- A priority queue is BIFO (Best-In, First-Out) structure.
- A deque behaves like a queue except that data can be added or removed from either end.
- Abstraction is the deliberate concealment of irrelevant detail.
- An Abstract Data Type is defined by the operations that it allows you to perform on its data. The implementation of these methods, and the means by which data are stored, are deliberately concealed.
- The Java collections framework contains classes and interfaces representing stacks, queues, priority queues, and deques.
Graphs
Content
- Basic graph definitions
- Implementation of graph data structures
- Traversals and applications
Graphs: Nodes and Edges
- Network-like data structures can be represented using graphs.
- A graph consists of a set of nodes (also known as vertices) together with a set of edges (also known as arcs) connecting them
- Some graphs may have loops (a loop is an edge connecting a node to itself)

Graphs: Directed and Undirected
- Graphs can be directed (e.g. a street map with one way streets)
- or undirected (e.g. street map where all streets can be traversed in any direction)

Example: Chengdu Subway

Graphs: Data Storage
- As well as the nodes and edge structure, graphs typically have additional data stored.
- This data can be at nodes and/or edges,
- For example: in the Chengdu Subway graph:
- nodes have names of stations
- edges are labeled with the line(s) between those stations
Implementing Graphs on a Computer
- There are two common ways of representing graph data:
- adjacency matrices
- adjacency lists
Adjacency Matrix
- This uses a two-dimensional array of booleans(note this is a static data structure)
- The array shows which edges are connected to which other edges.

- Please draw the adjacency matrix for following graph

Directed Graph:

Straightforward to program:
boolean[][] edgeMatrix = new boolean[n][n];An edge exists from node i to node j when edgeMatrix[i][j] is true
Adjacency Matrices
- Access to edge information is fast, due to use of arrays.
- Storage of node data
- use an additional array of information, one piece of information per node
- Storage of edge data
- use an additional 2D array of information, one piece of information per edge
Adjacency Matrices features
- Space usage:
- For a graph with nodes, it can have from to edges (including loops and counting two-way edges twice), so the space taken up in memory to store the graph using an adjacency matrix is the space required to store boolean values.
- If a graph is sparse (significantly fewer edges than ), this can be wasteful of space. There is a more efficient way of representing sparse graphs
Adjacency Lists
- For each node is stored a list of nodes that it connects to (note this is more of a dynamic data structure)
e.g. for a graph with n nodes labeled with integers, could use an array of length n, each pointing to the node’s adjacency list

- Please draw the adjacency list for following graph

Adjacency Lists: integer labels
- e.g. if the nodes are labeled by integers, an adjacency lists structure could be of type
ArrayList<Integer>[]- An edge exists from node
ito nodejwhenjis a node in the listadjacencyLists[i]
ArrayList<Interger> adjacencyLists[]= new ArrayList[n];Adjacency Lists: non-integer labels
- More generally, if there is a type
Nodefor the nodes of the graph, an adjacency list structure could be
ArrayList<Node> adjacencyLists = new ArrayList<Node>();- where each
Nodewould contain its own adjacency list of typeArrayList<Node>. - In this case, edge exists from node
nto nodemwhenmis a node in the adjacency list belonging to noden.
Class Teacher { ………… public ArrayList<Teacher> adjacencyLists = new ArrayList<Teacher>();}…………Teacher l,j,ja,jak;l.adjacencyLists.add(j);Adjacency Lists features
- Access to edge information is not as fast as an adjacency matrix, because the relevant list has to be traversed.
- However, the amount of memory required to store the adjacency lists can be less, as it is proportional to how many edges are in the graph.
More edges more space
Traversals
- A traversal is a way of systematically going through all the data in a structure, visiting each piece of data precisely once.
- Traversals can be used for various purposes, including searching.
- Two common types of graph traversal:
- Depth-first traversal
- Breadth-first traversal
3 traversal methods for binary tree
Depth-First Traversal
- Start at some node S
- If there is a node that is adjacent to S that you have not yet visited then visit it
- If there is an unvisited node adjacent to the one you just visited, then visit that.

- Keep on doing this until you come to a “dead end”, that is to say that you reach a node that either has no adjacent nodes at all, or where all the adjacent nodes have already been visited.
- When you get to a dead end, “backtrack” along the path that you just followed until you come to a node that has an unvisited adjacent node, and repeat the process from there.

Depth-First Traversal: Another Example

This traversal:
Different depth-first traversals are also possible, for example:
Depth-First Traversal: Notes
- DFT can be implemented on directed graphs (in that case, the edge directions must be respected) or on undirected graphs (every edge goes in both directions)
- DFT can be implemented using recursion, or using a stack of nodes (not covered in this lecture)
- In either case, a record needs to be kept of the set of nodes that have been visited
- this set could be represented as an array of booleans, for example, one boolean for each node.
Depth-First Traversal pseudocode (recursive version)
dft(g,n) { visit(n) mark n as visited for each node x adjacent to n { if x is unvisited then dft(g,x) }}Notes:
We assume that all nodes are originally marked as unvisited.
You don’t need to worry about what the visit method does (if you are worried, imagine that it just prints out the name of the node being visited).
Breadth-First Traversal
- Start at some point S
- Repeat
- Visit all the nodes adjacent to S
- Visit all the nodes adjacent to the ones you just visited (unless you have already visited them)
- And so on

Explores nodes in a pattern that “radiates out” from the start point.

Breadth-First Traversal Example
- Starting at the root node, visit all its neighbours before visiting all their neighbours, and so on.
One possible order of nodes visited using this method:
Note: as B was visited before C and D, B’s neighbors need to be visited before those of C and D.

Breadth-First Traversal: Notes
- BFT can also be implemented on directed graphs (respect the edge directions) or on undirected graphs (every edge goes in both directions)
- BFT is usually implemented using a queue of nodes (the queue holds nodes waiting to be visited). The queue is used in the same way the stack is used for DFT. [Code not covered.]
- Similarly as for DFT, a record needs to be kept of which nodes have been visited (e.g. in an array of booleans).
Using BFT/DFT to test connectivity

- Informally, an undirected graph is connected if you can draw it ALL without taking your pen off the paper (you may have to retrace some parts of it!)
Exercise
- To test the connectivity of an undirected* graph:
Algorithm:
Start from any node, do a BFT or DFT from that node, and test afterwards whether all the nodes were visited.

* It’s more complicated if the graph is directed.
Why?
Checklist
- What you want to be capable of by the end of this week:
- know basic graph terminology
- know suitable storage structures for graph data
- perform both depth-first and breadth-first traversals of graphs
- describe uses for graphs and traversals
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!