CHAPTER 4: Linked Structuresprofesor.uprb.edu/.../lewis_chase_chap04.pdf · * @author Lewis and...

47
© 2010 Pearson Addison-Wesley. All rights reserved. Addison Wesley is an imprint of CHAPTER 4: Linked Structures Java Software Structures: Designing and Using Data Structures Third Edition John Lewis & Joseph Chase

Transcript of CHAPTER 4: Linked Structuresprofesor.uprb.edu/.../lewis_chase_chap04.pdf · * @author Lewis and...

© 2010 Pearson Addison-Wesley. All rights reserved.

Addison Wesley

is an imprint of

CHAPTER 4:

Linked Structures

Java Software Structures:

Designing and Using Data Structures

Third Edition

John Lewis & Joseph Chase

1-2

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-3

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-4

© 2010 Pearson Addison-Wesley. All rights reserved. 1-4

References as Links

1-5

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

}

1-6

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-7

© 2010 Pearson Addison-Wesley. All rights reserved. 1-7

A linked list

1-8

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-9

© 2010 Pearson Addison-Wesley. All rights reserved. 1-9

A complex linked structure

1-10

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-11

© 2010 Pearson Addison-Wesley. All rights reserved. 1-11

Inserting a node at the front of a linked

list

1-12

© 2010 Pearson Addison-Wesley. All rights reserved. 1-12

Inserting a node in the middle of a linked

list

1-13

© 2010 Pearson Addison-Wesley. All rights reserved. 1-13

Deleting the first node in a linked list

1-14

© 2010 Pearson Addison-Wesley. All rights reserved. 1-14

Deleting an interior node from a linked list

1-15

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-16

© 2010 Pearson Addison-Wesley. All rights reserved. 1-16

Using separate node objects to store and

link elements

1-17

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-18

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-19

© 2010 Pearson Addison-Wesley. All rights reserved. 1-19

A doubly linked list

1-20

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-21

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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;

}

1-22

© 2010 Pearson Addison-Wesley. All rights reserved. 1-22

The LinearNode class (continued)

/**

* Creates a node storing the specified element.

* @param elem element to be stored

*/

public LinearNode (T elem)

{

next = null;

element = elem;

}

/**

* Returns the node that follows this one.

* @return LinearNode<T> reference to next node

*/

public LinearNode<T> getNext()

{

return next;

}

/**

* Sets the node that follows this one.

* @param node node to follow this one

*/

1-23

© 2010 Pearson Addison-Wesley. All rights reserved. 1-23

The LinearNode class (continued)

public void setNext (LinearNode<T> node)

{

next = node;

}

/**

* Returns the element stored in this node.

* @return T element stored at this node

*/

public T getElement()

{

return element;

}

/**

* Sets the element stored in this node.

* @param elem element to be stored at this node

*/

public void setElement (T elem)

{

element = elem;

}

}

1-24

© 2010 Pearson Addison-Wesley. All rights reserved. 1-24

A linked implementation of a stack

collection

1-25

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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;

}

1-26

© 2010 Pearson Addison-Wesley. All rights reserved. 1-26

An initial stack

1-27

© 2010 Pearson Addison-Wesley. All rights reserved. 1-27

LinkedStack – the push operation

/**

* Adds the specified element to the top of this stack.

* @param 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++;

}

1-28

© 2010 Pearson Addison-Wesley. All rights reserved. 1-28

A Linked Stack After a Push Operation

1-29

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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.

* @return T element from top of stack

* @throws 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;

}

1-30

© 2010 Pearson Addison-Wesley. All rights reserved. 1-30

A Linked Stack After a Pop Operation

1-31

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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.

1-32

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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)

1-33

© 2010 Pearson Addison-Wesley. All rights reserved. 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

1-34

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-35

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-36

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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;

1-37

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

* @param x represents x coordinate

* @param y represents y coordinate

* @param stack the working stack of moves within the grid

* @return StackADT<Position> stack of moves within the grid

*/

1-38

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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.

* @return boolean returns true if the maze is successfully traversed

*/

1-39

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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);

}

}

1-40

© 2010 Pearson Addison-Wesley. All rights reserved. 1-40

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;

}

1-41

© 2010 Pearson Addison-Wesley. All rights reserved. 1-41

The Maze class (continued)

/**

* Returns the maze as a string.

* @return 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;

}

}

1-42

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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.

* @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);

}

}

1-43

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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;

}

1-44

© 2010 Pearson Addison-Wesley. All rights reserved. 1-44

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-45

© 2010 Pearson Addison-Wesley. All rights reserved. 1-45

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-46

© 2010 Pearson Addison-Wesley. All rights reserved. 1-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

1-47

© 2010 Pearson Addison-Wesley. All rights reserved. 1-47

A UML description of the java.util.Stack

class