CHAPTER 4 Linked Structures Java Software Structures Designing















































- Slides: 47
CHAPTER 4: Linked Structures Java Software Structures: Designing and Using Data Structures Third Edition John Lewis & Joseph Chase Addison Wesley is an imprint of © 2010 Pearson Addison-Wesley. All rights reserved.
Chapter Objectives • Describe the use of references to create linked structures • Compare linked structures to array-based structures • Explore the techniques for managing a linked list • Discuss the need for a separate node to form linked structures • Implement a stack collection using a linked list 1 -2 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -2
References as Links • There are many ways to implement a collection • In chapter 3 we explored an array-based implementation of a stack collection • A linked structure uses object reference variables to link one object to another • Recall that an object reference variable stores the address of an object • In that sense, an object reference is a pointer to an object 1 -3 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -3
References as Links 1 -4 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -4
Self-Referential Objects • A Person object, for instance, could contain a reference variable to another Person object: public class Person { private String name; private String address; private Person next; object // a link to another Person // whatever else } 1 -5 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -5
Linked Lists • This type of reference can be used to form a linked list, in which one object refers to the next, which refers to the next, etc. • Each object in a list is often generically called a node • A linked list is a dynamic data structure in that its size grows and shrinks as needed, unlike an array, whose size is static or fixed • Java objects are created dynamically when they are instantiated 1 -6 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -6
A linked list 1 -7 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -7
Non-linear Structures • A linked list, as the name implies, is a linear structure • Object references also allow us to create non-linear structures such as hierarchies and graphs 1 -8 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -8
A complex linked structure 1 -9 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -9
Managing Linked Lists • The references in a linked list must be carefully managed to maintain the integrity of the structure • Special care must be taken to ensure that the entry point into the list is maintained properly • The order in which certain steps are taken is important • Consider inserting and deleting nodes in various positions within the list 1 -10 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -10
Inserting a node at the front of a linked list 1 -11 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -11
Inserting a node in the middle of a linked list 1 -12 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -12
Deleting the first node in a linked list 1 -13 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -13
Deleting an interior node from a linked list 1 -14 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -14
Elements without Links • The problem with self-referential objects is that they must "know" they are part of a list • A better approach is to manage a separate list of nodes that also reference the objects stored in the list • The list is still managed using the same techniques • The objects stored in the list need no special implementation to be part of the list • A generic list collection can be used to store any kind of object 1 -15 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -15
Using separate node objects to store and link elements 1 -16 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -16
Sentinel nodes • There are variations on the implementation of linked lists that may be useful in particular situations • One such solution is the use of sentinel nodes or dummy nodes on either end of the list • This practice eliminates the special cases of inserting or deleting the first or last node 1 -17 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -17
Doubly Linked Lists • Another useful variation is a doubly linked list • In a doubly linked list each node has a reference to both the next and previous nodes in the list • This makes traversing the list easier 1 -18 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -18
A doubly linked list 1 -19 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -19
Implementing a stack with links • We can use a linked list to implement our stack collection from chapter 3 • First, however, we will need to create a Linear. Node class to represent a node in the list 1 -20 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -20
The Linear. Node class /** * @author Lewis and Chase * * Represents a node in a linked list. */ package jss 2; public class Linear. Node<T> { /** reference to next node in list */ private Linear. Node<T> next; /** element stored at this node */ private T element; /** * Creates an empty node. */ public Linear. Node() { next = null; element = null; } 1 -21 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -21
The Linear. Node class (continued) /** * Creates a node storing the specified element. * @param element to be stored */ public Linear. Node (T elem) { next = null; element = elem; } /** * Returns the node that follows this one. * @return Linear. Node<T> reference to next node */ public Linear. Node<T> get. Next() { return next; } /** * Sets the node that follows this one. * @param node to follow this one */ © 2010 Pearson Addison-Wesley. All rights reserved. 1 -22
The Linear. Node class (continued) public void set. Next (Linear. Node<T> node) { next = node; } /** * Returns the element stored in this node. * @return T element stored at this node */ public T get. Element() { return element; } /** * Sets the element stored in this node. * @param element to be stored at this node */ public void set. Element (T elem) { element = elem; } } © 2010 Pearson Addison-Wesley. All rights reserved. 1 -23
A linked implementation of a stack collection 1 -24 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -24
Linked. Stack /** * @author Lewis and Chase * * Represents a linked implementation of a stack. */ package jss 2; import jss 2. exceptions. *; import java. util. Iterator; public class Linked. Stack<T> implements Stack. ADT<T> { /** indicates number of elements stored */ private int count; /** pointer to top of stack */ private Linear. Node<T> top; /** * Creates an empty stack. */ public Linked. Stack() { count = 0; top = null; } © 2010 Pearson Addison-Wesley. All rights reserved. 1 -25
An initial stack 1 -26 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -26
Linked. Stack – the push operation /** * Adds the specified element to the top of this stack. * @param element to be pushed on stack */ public void push (T element) { Linear. Node<T> temp = new Linear. Node<T> (element); temp. set. Next(top); top = temp; count++; } 1 -27 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -27
A Linked Stack After a Push Operation 1 -28 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -28
Linked. Stack – the pop operation /** * Removes the element at the top of this stack and returns a * reference to it. Throws an Empty. Collection. Exception if the stack * is empty. * @return T element from top of stack * @throws Empty. Collection. Exception on pop from empty stack */ public T pop() throws Empty. Collection. Exception { if (is. Empty()) throw new Empty. Collection. Exception("Stack"); T result = top. get. Element(); top = top. get. Next(); count--; return result; } 1 -29 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -29
A Linked Stack After a Pop Operation 1 -30 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -30
Linked. Stack – the other operations • Using a linked implementation, the peek operation is implemented by returning a reference to top • The is. Empty operation returns true if the count of elements is 0, and false otherwise • The size operation simply returns the count of elements in the stack • The to. String operation can be implemented by simply traversing the linked list. 1 -31 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -31
Analysis of Stack Operations • Like our Array. Stack operations, the Linked. Stack operations work on one end of the collection and are generally efficient • The push and pop operations, for the linked implementation are O(1) • Likewise, the other operations are also O(1) 1 -32 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -32
Using Stacks - Traversing a Maze • A classic use of a stack is to keep track of alternatives in maze traversal or other trial and error algorithms • Using a stack in this way simulates recursion – Recursion is when a method calls itself either directly or indirectly 1 -33 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -33
Using Stacks - Traversing a Maze • Run-time environments keep track of method calls by placing an activation record for each called method on the run-time stack • When a method completes execution, it is popped from the stack and control returns to the method that called it – Which is now the activation record on the top of the stack 1 -34 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -34
Using Stacks - Traversing a Maze • In this manner, we can traverse a maze by trial and error by using a stack to keep track of moves that have not yet been tried 1 -35 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -35
The Maze class /** * @author Lewis and Chase * * Represents a maze of characters. The goal is to get from the * top left corner to the bottom right, following a path of 1's. */ import jss 2. *; public class Maze { /** * constant to represent tried paths */ private final int TRIED = 3; /** * constant to represent the final path */ private final int PATH = 7; 1 -36 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -36
The Maze class (continued) /** * two dimensional array representing the grid */ private int [][] grid = { {1, 1, 1, 0, 0, 0, 1, 1}, {1, 0, 0, 1, 1, 0, 0, 1}, {1, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 0, 1, 1, 1}, {1, 1, 1, 0, 1, 1, 1}, {1, 0, 0, 1, 1, 1, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 1, 1}, {1, 0, 0, 0, 0}, {1, 1, 1, 1} }; /** * push a new attempted move onto the stack * @param x represents x coordinate * @param y represents y coordinate * @param stack the working stack of moves within the grid * @return Stack. ADT<Position> stack of moves within the grid */ 1 -37 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -37
The Maze class (continued) private Stack. ADT<Position> push_new_pos(int x, int y, Stack. ADT<Position> stack) { Position npos = new Position(); npos. setx(x); npos. sety(y); if (valid(npos. getx(), npos. gety())) stack. push(npos); return stack; } /** * Attempts to iteratively traverse the maze. It inserts special * characters indicating locations that have been tried and that * eventually become part of the solution. This method uses a * stack to keep track of the possible moves that could be made. * @return boolean returns true if the maze is successfully traversed */ 1 -38 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -38
The Maze class (continued) public boolean traverse () { boolean done = false; Position pos = new Position(); Object dispose; Stack. ADT<Position> stack = new Linked. Stack<Position>(); stack. push(pos); while (!(done)) { pos = stack. pop(); grid[pos. getx()][pos. gety()] = TRIED; // this cell has been tried if (pos. getx() == grid. length-1 && pos. gety() == grid[0]. length-1) done = true; // the maze is solved else { stack = push_new_pos(pos. getx(), pos. gety() - 1, stack); stack = push_new_pos(pos. getx(), pos. gety() + 1, stack); stack = push_new_pos(pos. getx() - 1, pos. gety(), stack); stack = push_new_pos(pos. getx() + 1, pos. gety(), stack); } } © 2010 Pearson Addison-Wesley. All rights reserved. 1 -39
The Maze class (continued) return done; } /** * Determines if a specific location is valid. * @param row int representing y coordinate * @param column int representing x coordinate * @return boolean true if the given coordinate is a valid move */ private boolean valid (int row, int column) { boolean result = false; /** Check if cell is in the bounds of the matrix */ if (row >= 0 && row < grid. length && column >= 0 && column < grid[row]. length) /** Check if cell is not blocked and not previously tried */ if (grid[row][column] == 1) result = true; return result; } © 2010 Pearson Addison-Wesley. All rights reserved. 1 -40
The Maze class (continued) /** * Returns the maze as a string. * @return String representation of the maze grid */ public String to. String () { String result = "n"; for (int row=0; row < grid. length; row++) { for (int column=0; column < grid[row]. length; column++) result += grid[row][column] + ""; result += "n"; } return result; } } 1 -41 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -41
The Maze. Search class /** * @author Lewis and Chase * * Demonstrates a simulation of recursion using a stack. */ public class Maze. Search { /** * Creates a new maze, prints its original form, attempts to * solve it, and prints out its final form. * @param args array of Strings */ public static void main (String[] args) { Maze labyrinth = new Maze(); System. out. println (labyrinth); if (labyrinth. traverse ()) System. out. println ("The maze was successfully traversed!"); else System. out. println ("There is no possible path. "); System. out. println (labyrinth); } } © 2010 Pearson Addison-Wesley. All rights reserved. 1 -42
The Position class /** * @author Lewis and Chase * * Represents a single position in a maze of characters. */ public class Position { /** x coordinate */ private int x; /** y coordinate */ private int y; /** * Constructs a position and sets the x & y coordinates to 0, 0. */ Position () { x = 0; y = 0; } 1 -43 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -43
The Position class (continued) /** * Returns the x-coordinate value of this position. * @return int the x-coordinate of this position */ public int getx() { return x; } /** * Returns the y-coordinate value of this position. * @return int the y-coordinate of this position */ public int gety() { return y; } 1 -44 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -44
The Position class (continued) /** * Sets the value of the current position's x-coordinate. * @param a value of x-coordinate */ public void setx(int a) { x = a; } /** * Sets the value of the current position's x-coordinate. * @param a value of y-coordinate */ public void sety(int a) { y = a; } } 1 -45 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -45
The java. util. Stack Class • The Java Collections framework defines a Stack class with similar operations • It is derived from the Vector class and therefore has some characteristics that are not appropriate for a pure stack • The java. util. Stack class has been around since the original version of Java, and has been retrofitted to meld with the Collections framework 1 -46 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -46
A UML description of the java. util. Stack class 1 -47 © 2010 Pearson Addison-Wesley. All rights reserved. 1 -47