Presentation is loading. Please wait.

Presentation is loading. Please wait.

CHAPTER 4: Linked Structures

Similar presentations


Presentation on theme: "CHAPTER 4: Linked Structures"— Presentation transcript:

1 CHAPTER 4: Linked Structures
Java Software Structures: Designing and Using Data Structures Third Edition John Lewis & Joseph Chase

2 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

3 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

4 References as Links

5 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; // a link to another Person object // whatever else }

6 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

7 A linked list

8 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

9 A complex linked structure

10 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

11 Inserting a node at the front of a linked list

12 Inserting a node in the middle of a linked list

13 Deleting the first node in a linked list

14 Deleting an interior node from a linked list

15 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

16 Using separate node objects to store and link elements

17 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

18 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

19 A doubly linked list

20 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 LinearNode class to represent a node in the list

21 The LinearNode class /** * @author Lewis and Chase *
* Represents a node in a linked list. */ package jss2; public class LinearNode<T> { /** reference to next node in list */ private LinearNode<T> next; /** element stored at this node */ private T element; * Creates an empty node. public LinearNode() next = null; element = null; }

22 The LinearNode class (continued)
/** * Creates a node storing the specified element. elem element to be stored */ public LinearNode (T elem) { next = null; element = elem; } * Returns the node that follows this one. LinearNode<T> reference to next node public LinearNode<T> getNext() return next; * Sets the node that follows this one. node node to follow this one

23 The LinearNode class (continued)
public void setNext (LinearNode<T> node) { next = node; } /** * Returns the element stored in this node. T element stored at this node */ public T getElement() return element; * Sets the element stored in this node. elem element to be stored at this node public void setElement (T elem) element = elem;

24 A linked implementation of a stack collection

25 LinkedStack /** * @author Lewis and Chase *
* Represents a linked implementation of a stack. */ package jss2; import jss2.exceptions.*; import java.util.Iterator; public class LinkedStack<T> implements StackADT<T> { /** indicates number of elements stored */ private int count; /** pointer to top of stack */ private LinearNode<T> top; * Creates an empty stack. public LinkedStack() count = 0; top = null; }

26 An initial stack

27 LinkedStack – the push operation
/** * Adds the specified element to the top of this stack. element element to be pushed on stack */ public void push (T element) { LinearNode<T> temp = new LinearNode<T> (element); temp.setNext(top); top = temp; count++; }

28 A Linked Stack After a Push Operation

29 LinkedStack – the pop operation
/** * Removes the element at the top of this stack and returns a * reference to it. Throws an EmptyCollectionException if the stack * is empty. T element from top of stack EmptyCollectionException on pop from empty stack */ public T pop() throws EmptyCollectionException { if (isEmpty()) throw new EmptyCollectionException("Stack"); T result = top.getElement(); top = top.getNext(); count--; return result; }

30 A Linked Stack After a Pop Operation

31 LinkedStack – the other operations
Using a linked implementation, the peek operation is implemented by returning a reference to top The isEmpty 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 toString operation can be implemented by simply traversing the linked list.

32 Analysis of Stack Operations
Like our ArrayStack operations, the LinkedStack 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)

33 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

34 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

35 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

36 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 jss2.*; public class Maze { * constant to represent tried paths private final int TRIED = 3; * constant to represent the final path private final int PATH = 7;

37 The Maze class (continued)
/** * two dimensional array representing the grid */ private int [][] grid = { {1,1,1,0,1,1,0,0,0,1,1,1,1}, {1,0,0,1,1,0,1,1,1,1,0,0,1}, {1,1,1,1,1,0,1,0,1,0,1,0,0}, {0,0,0,0,1,1,1,0,1,0,1,1,1}, {1,1,1,0,1,1,1,0,1,0,1,1,1}, {1,0,1,0,0,0,0,1,1,1,0,0,1}, {1,0,1,1,1,1,1,1,0,1,1,1,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,1,1,1,1,1,1} }; * push a new attempted move onto the stack x represents x coordinate y represents y coordinate stack the working stack of moves within the grid StackADT<Position> stack of moves within the grid

38 The Maze class (continued)
private StackADT<Position> push_new_pos(int x, int y, StackADT<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. boolean returns true if the maze is successfully traversed */

39 The Maze class (continued)
public boolean traverse () { boolean done = false; Position pos = new Position(); Object dispose; StackADT<Position> stack = new LinkedStack<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); }

40 The Maze class (continued)
return done; } /** * Determines if a specific location is valid. row int representing y coordinate column int representing x coordinate 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;

41 The Maze class (continued)
/** * Returns the maze as a string. String representation of the maze grid */ public String toString () { 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;

42 The MazeSearch class /** * @author Lewis and Chase *
* Demonstrates a simulation of recursion using a stack. */ public class MazeSearch { * Creates a new maze, prints its original form, attempts to * solve it, and prints out its final form. 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."); }

43 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; }

44 The Position class (continued)
/** * Returns the x-coordinate value of this position. int the x-coordinate of this position */ public int getx() { return x; } * Returns the y-coordinate value of this position. int the y-coordinate of this position public int gety() return y;

45 The Position class (continued)
/** * Sets the value of the current position's x-coordinate. a value of x-coordinate */ public void setx(int a) { x = a; } a value of y-coordinate public void sety(int a) y = a;

46 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

47 A UML description of the java.util.Stack class


Download ppt "CHAPTER 4: Linked Structures"

Similar presentations


Ads by Google