Presentation is loading. Please wait.

Presentation is loading. Please wait.

*Basic Link Operations *Queues, Stack, Trees

Similar presentations


Presentation on theme: "*Basic Link Operations *Queues, Stack, Trees"— Presentation transcript:

1 *Basic Link Operations *Queues, Stack, Trees
Chapter 12 The slides for this chapter are based on slides made by Professor Jeff Rosenschein, Computer-Science Department, The Hebrew University, Jerusalem, Israel. *Linked Lists *Basic Link Operations *Queues, Stack, Trees

2 Object Variable Contains Object’s Address in the Heap
A object variable represents the address, in computer memory, of an object. dinnertime Attributes: hour = 0 minute = 0 Methods: … dinnertime heap

3 Object Variable Contains Object’s Address in the Heap
A object variable represents the address, in computer memory, of an object. dinnertime Attributes: hour = 0 minute = 0 Methods: … 32476 dinnertime 32476 heap

4 Dynamically Allocated Objects with Pointers to other Objects
class DataObject { int myNumber; DataObject next; … } Objects of class DataObject can contain variables of type DataObject. The variable "next" is really just a reference to an object of type DataObject; it can also be the reference null (which marks the end of the linked list).

5 Linked List class DataObject { int myNumber; DataObject next; … } heap
first second Attributes: myNumber = next = Methods: … Attributes: myNumber = next = null Methods: … heap

6 Linked List class DataObject { int myNumber; DataObject next; … }
first second Attributes: myNumber = next = Methods: … Attributes: myNumber = next = null Methods: … 29371 32476 heap

7 Time lunchtime = new Time(12, 0), dinnertime = new Time(0, 0);
Set aside storage for an address, and create the object (putting its address in that storage) Time lunchtime = new Time(12, 0), dinnertime = new Time(0, 0); dinnertime Attributes: hour = 0 minute = 0 Methods: … I write the names here to help you identify the objects; in reality, the objects in the heap have no names attached dinnertime lunchtime Attributes: hour = minute = 0 Methods: … lunchtime

8 A Clarification I have used an object name (like "dinnertime" or "lunchtime") to refer both to the reference and to the object itself. There's a reason for this…

9 Sometimes we are speaking of attributes of the object itself
dinnertime.hour = lunchtime.hour; means that the hour attribute inside the dinnertime object gets the value of the hour attribute inside the lunchtime object:

10 But sometimes we are referring to the address of the object
dinnertime = lunchtime; means the contents of the lunchtime reference (an address) get put into the dinnertime reference location:

11 The node has room for an address
What's inside the linked list node is a storage location for an address, just like the storage location "dinnertime" or "lunchtime": first second Attributes: myNumber = next = Methods: … Attributes: myNumber = next = null Methods: … heap

12 The node has room for an address
We can make an assignment from "first.next" into "current" and it means the contents of one (the address) go into the other: current = first.next; first second Attributes: myNumber = next = Methods: … Attributes: myNumber = next = null Methods: … heap

13 Linked List Example (1) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; null null first current Address of object first: null Object first: --- Address of object current: null Object current: ---

14 Linked List Example (2) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; null first current Attributes: letter = null next = null Methods: … Address of object first: Object first: (null, null) Address of object current: null Object current: ---

15 Linked List Example (3) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; first current Attributes: letter = null next = null Methods: … Address of object first: Object first: (null, null) Address of object current: Object current: (null, null)

16 Linked List Example (4) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; first current Attributes: letter = 'A' next = null Methods: … Address of object first: Object first: ('A', null) Address of object current: Object current: ('A', null)

17 Linked List Example (5) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; first current Attributes: letter = 'A' next = Methods: … Attributes: letter = null next = null Methods: … Address of object first: Object first: ('A', ) Address of object current: Object current: ('A', )

18 Linked List Example (6) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; first current Attributes: letter = 'A' next = Methods: … Attributes: letter = null next = null Methods: … Address of object first: Object first: ('A', ) Address of object current: Object current: (null, null)

19 Linked List Example (7) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; first current Attributes: letter = 'A' next = Methods: … Attributes: letter = 'B' next = null Methods: … Address of object first: Object first: ('A', ) Address of object current: Object current: ('B', null)

20 Linked List Example (8) class Node { char letter; Node next; … }
Node first, current; first = new Node( ); current = first; first.letter = ‘A’; first.next = new Node( ); current = current.next; current.letter = ‘B’; current.next = null; first current Attributes: letter = 'A' next = Methods: … Attributes: letter = 'B' next = null Methods: … Address of object first: Object first: ('A', ) Address of object current: Object current: ('B', null)

21 Linked List (9) 748921 647361 class Node { char letter; Node next; … }
Address of object first: Object first: (‘A’, ) Address of object current: Object current: (‘B’, null) first current Attributes: letter = A next = Methods: … Attributes: letter = B next = null Methods: … 748921 647361 heap

22 Basic Link Operations The individual objects in a linked list are called a cell or a node The reference to the next cell is called a link The first cell in a list is called the head of the list The remainder of the list is called its tail null I'll often leave out the "box" picture for the object variable (e.g., "firstNode") from now on next firstNode data >>>> >>>> null next next next data data data firstNode

23 The definition underlying the basic cell
class Node { int data; Node next; } Every reference should have an address or be null. Node firstNode = new Node( ); firstNode.next = new Node( ); firstNode.next.next = new Node( ); firstNode.next.next.next = new Node( ); firstNode.next.next.next.next = null; firstNode >>>> >>>> >>>> null next next next next data data data data

24 What do the names refer to?
class Node { int data; Node next; } firstNode represents an address of an object firstNode.data one attribute of the object at that address firstNode.next represents an address of an object firstNode.next.data one attribute of the object at that address firstNode >>>> >>>> >>>> null next next next next data data data data

25 Let's Make it More Encapsulated
class ListNode { private int value; private ListNode tail; public ListNode (int v, ListNode next) { value = v; tail = next; } public int getValue ( ) { return value; } public ListNode getTail ( ) { return tail; } }

26 Why did we build the linked list in reverse order?
Build a Linked List cell1 >>>> >>>> >>>> null tail tail tail tail 17 10945 616 -14 value value value value cell2 cell3 cell4 ListNode cell4 = new ListNode(-14, null); ListNode cell3 = new ListNode(616, cell4); ListNode cell2 = new ListNode(10945, cell3); ListNode cell1 = new ListNode(17, cell2); Why did we build the linked list in reverse order?

27 We Don't Need Separate Variables for each Node
list >>>> >>>> >>>> null tail tail tail tail 17 10945 616 -14 value value value value ListNode list = new ListNode(-14, null); list = new ListNode(616, list); list = new ListNode(10945, list); list = new ListNode(17, list); With each line, list points to one node further to the left

28 You Can Even Embed the Calls to new
list >>>> >>>> >>>> null tail tail tail tail 17 10945 616 -14 value value value value ListNode list = new ListNode(17, new ListNode(10945, new ListNode(616, new ListNode(-14, null)))); Notice that the order of the nodes now matches their final order --- but the rightmost is still created first

29 Questions list What is the effect of (independently):
>>>> >>>> >>>> null tail tail tail tail 17 10945 616 -14 value value value value What is the effect of (independently): a) list = list.getTail( );

30 Questions list What is the effect of (independently):
>>>> >>>> >>>> null tail tail tail tail 17 10945 616 -14 value value value value What is the effect of (independently): a) list = list.getTail( ); a) Makes list point to second object (and thus removes first object from the list)

31 Questions list What is the effect of (independently):
>>>> >>>> >>>> null tail tail tail tail 17 10945 616 -14 value value value value What is the effect of (independently): a) list = list.getTail( ); b) list.tail = list; // Assume tail is not private a) Makes list point to second object (and thus removes first object from the list)

32 Questions list What is the effect of (independently):
>>>> >>>> >>>> null tail tail tail tail 17 10945 616 -14 value value value value What is the effect of (independently): a) list = list.getTail( ); b) list.tail = list; // Assume tail is not private a) Makes list point to second object (and thus removes first object from the list) b) Makes the first object's tail field point to the first object (and thus loses the rest of the list)

33 Queues, Stacks, Trees Linked lists (such as above) are the main building blocks of a variety of data abstractions: Queues: new records added to one end and taken from the other end; first-in, first-out, FIFO Stacks: new records added to one end and taken off from the same end; last-in, first-out, LIFO Trees: can have more than one linked list attached to each node

34 Basic Link Manipulation
maintaining auxiliary pointers to different parts of a list (especially first and last nodes) adding to the end of a linked list traveling through an entire list searching for a particular node inserting into the middle of a linked list merging two lists together or inserting one list into another deleting individual nodes or sublists

35 Auxiliary Pointers, and Extending a List
currentNode = firstNode.next.next.next; firstNode >>>> >>>> >>>> null next next next next undefined undefined undefined undefined data data data data currentNode currentNode.next = new Node( ); currentNode = currentNode.next; currentNode.next = null; firstNode >>>> >>>> >>>> >>>> null next next next next next undefined undefined undefined undefined undefined data data data data data currentNode

36 Questions firstNode currentNode
>>>> >>>> >>>> >>>> null next next next next next undefined undefined undefined undefined undefined data data data data data currentNode What is the effect of making the assignment: currentNode.next = firstNode;

37 Questions firstNode currentNode
>>>> >>>> >>>> >>>> null next next next next next undefined undefined undefined undefined undefined data data data data data currentNode What is the effect of making the assignment: currentNode.next = firstNode; firstNode >>>> >>>> >>>> >>>> >>>> next next next next next undefined undefined undefined undefined undefined data data data data data currentNode We get a circular list.

38 Going to the End of a List
Goal: Have a pointer to the list’s last node. Bound: The current node’s next field is null. Plan: Advance a pointer to the next node in the list. // Precondition: currentNode addresses any node while ( currentNode.next != null ) { currentNode = currentNode.next; } // Postcondition: currentNode addresses the last node Be careful about the bounds (looking for an item or the node before an item? bounded by the list’s last node or by the null value that ends the list?)

39 Searching for a Node Goal: Have a pointer to the node that has a particular data field. Intentional bound: Current node’s data field is the one we want. Necessary bound: The current node’s next field is null. Plan: Advance a pointer to the next node in the list. // Precondition: firstNode addresses any node currentNode = firstNode; //start at the beginning while ( (currentNode.data != soughtValue) && (currentNode.next != null) ) { currentNode = currentNode.next; } // Postcondition: If soughtValue is there, it’s in currentNode if ( currentNode.data == soughtValue ) System.out.println("Value found."); else System.out.println("Value not found.");

40 An Example: Creating and Printing a List
Read a sequence of positive numbers that ends with a zero or negative sentinel. Print the sentinel, then echo the sequence in the order in which it was typed in. Initialize Create the List Print the List

41 The First Two Steps initialize the list by allocating its first node, via firstNode; point an auxiliary pointer currentNode to the first node; read theNumber; while ( it isn’t the sentinel ) { add a new node to the end of the list; advance the currentNode reference to it; make its next field null; save theNumber in it; read the next theNumber; } // Postcondition: the first stored value is in the node that // follows firstNode; the last stored value is in the node // whose next field is null

42 Now Print the List’s Contents
// Remember the first node’s data field is undefined point currentNode to the first node again; while (the current node’s next field isn’t null) { advance the currentNode reference to the next node; print the current node’s data field; } // Postcondition: We’ve printed every defined // data field in the list

43 class Node { int data; Node next; } class LinkEcho { public static void main (String[ ] args) { Node firstNode, currentNode; int theNumber; firstNode = new Node( ); firstNode.next = null; currentNode = firstNode; System.out.println("Enter numbers, negative sentinel"); theNumber = (int) cse_io.readNum( ); while ( theNumber > 0 ) { currentNode.next = new Node( ); currentNode = currentNode.next; currentNode.next = null; currentNode.data = theNumber; } currentNode = firstNode; // Its data field is empty while ( currentNode.next != null ) { System.out.print(currentNode.data); different file

44 Inserting Nodes Let’s say we want to insert a node right after the node pointed to by current firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current

45 Inserting Nodes Let’s say we want to insert a node right after the node pointed to by current temp = new Node( ); firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current null next temp data

46 Inserting Nodes Let’s say we want to insert a node right after the node pointed to by current temp = new Node( ); temp.data = 3000; firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current null next 3000 temp data

47 Inserting Nodes Let’s say we want to insert a node right after the node pointed to by current temp = new Node( ); temp.data = 3000; temp.next = current.next; // order is crucial firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current >>>> next 3000 temp data

48 Inserting Nodes Let’s say we want to insert a node right after the node pointed to by current temp = new Node( ); temp.data = 3000; temp.next = current.next; // order is crucial current.next = temp; firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current >>>> next 3000 temp data

49 Inserting a new Node Before the Current Pointer Position (!)
firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current >>>> next freshNode 3000 Data data

50 Inserting a new Node Before the Current Pointer Position (!)
temp = new Node( ); firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current null >>>> next next freshNode 3000 temp Data data data

51 Inserting a new Node Before the Current Pointer Position (!)
temp = new Node( ); temp.data = current.data; firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current null >>>> next next 4000 freshNode 3000 temp Data data data

52 Inserting a new Node Before the Current Pointer Position (!)
temp = new Node( ); temp.data = current.data; temp.next = current.next; firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current >>>> >>>> next next 4000 freshNode 3000 temp Data data data

53 Inserting a new Node Before the Current Pointer Position (!)
temp = new Node( ); temp.data = current.data; temp.next = current.next; current.next = temp; firstNode >>>> >>>> >>>> null next next next next 1000 2000 4000 5000 data data data data current >>>> >>>> next next 4000 freshNode 3000 temp Data data data

54 Inserting a new Node Before the Current Pointer Position (!)
temp = new Node( ); temp.data = current.data; temp.next = current.next; current.next = temp; current.data = freshNode.data; firstNode >>>> >>>> >>>> null next next next next 1000 2000 3000 5000 data data data data current >>>> >>>> next next 4000 freshNode 3000 temp Data data data

55 Inserting a new Node Before the Current Pointer Position (!)
temp = new Node( ); temp.data = current.data; temp.next = current.next; current.next = temp; current.data = freshNode.data; freshNode = current; firstNode >>>> >>>> >>>> null next next next next 1000 2000 3000 5000 data data data data current >>>> >>>> next next 4000 freshNode 3000 temp Data data data

56 Inserting a new Node Before the Current Pointer Position (!)
temp = new Node( ); temp.data = current.data; temp.next = current.next; current.next = temp; current.data = freshNode.data; freshNode = current; current = current.next; firstNode >>>> >>>> >>>> null next next next next 1000 2000 3000 5000 data data data data current >>>> >>>> next next 4000 freshNode 3000 temp Data data data

57 Inserting a Sublist newHead newEnd currentNode next next next Data
>>>> >>>> null next next next newHead 3000 4000 5000 Data data data data newEnd >>>> >>>> >>>> >>>> next next next next 1000 2000 6000 7000 data data data data currentNode

58 Inserting a Sublist newEnd.next = currentNode.next; newHead newEnd
>>>> >>>> >>>> next next next newHead 3000 4000 5000 Data data data data newEnd >>>> >>>> >>>> >>>> next next next next 1000 2000 6000 7000 data data data data currentNode

59 Inserting a Sublist  newEnd.next = currentNode.next;
currentNode.next = newHead; >>>> >>>> >>>> next next next newHead 3000 4000 5000 Data data data data newEnd >>>> >>>> >>>> >>>> next next next next 1000 2000 6000 7000 data data data data currentNode

60 Deleting a Sublist currentNode lastBadNode next next next next next
>>>> >>>> >>>> >>>> >>>> next next next next next 1000 2000 2667 2668 3000 data data data data data currentNode lastBadNode

61 Deleting a Sublist  currentNode.next = lastBadNode.next; currentNode
>>>> >>>> >>>> >>>> >>>> next next next next next 1000 2000 2667 2668 3000 data data data data data currentNode lastBadNode

62 Deleting a Sublist What does this do? currentNode.next = lastBadNode;
>>>> >>>> >>>> >>>> >>>> next next next next next 1000 2000 2667 2668 3000 data data data data data currentNode lastBadNode What does this do? currentNode.next = lastBadNode;

63 Deleting a Sublist (not)
>>>> >>>> >>>> >>>> >>>> next next next next next 1000 2000 2667 2668 3000 data data data data data currentNode lastBadNode What does this do? currentNode.next = lastBadNode;

64 Another (2-class) Encapsulation of a Linked List (here's the node)
class IntNode { private int value; private IntNode next; public IntNode(int val, IntNode n) { value = val; next = n; } public IntNode getNext( ) { return next; } public void setNext(IntNode node) {next = node;}

65 The Actual List Class class IntList { private IntNode head;
IntList( ) { head = null; } boolean empty( ) { return head == null; } // add a link at the end of the list add(IntNode node) { if(empty( )) head = node; else { IntNode ptr = head; while(ptr.getNext( )!=null) ptr = ptr.getNext( ); ptr.setNext(node); } }

66 Let's Use This Encapsulated Definition of a Node Object
class ListNode { private int value; private ListNode tail; public ListNode (int v, ListNode next) { value = v; tail = next; } public int getValue ( ) { return value; } public ListNode getTail ( ) { return tail; } }

67 Recursive Functions Over Lists
Linked Lists (and other data structures using links) are well suited for recursive treatment, just as arrays are Example: Read in a list of positive numbers from the user (any length), then print them in reverse order Solve it recursively

68 User Enters: 11, 7, 5, 3, 2 Enter number: 2 Enter number: 3
We create: >>>> >>>> >>>> >>>> null tail tail tail tail tail theList 11 7 5 3 2 value value value value value We print: 11, 7, 5, 3, 2

69 Outline of Solution class PrintReversed {
static ListNode readReverseList ( ) { … } static void printReverseList(ListNode n) {…} public static void main (String[ ] args) { ListNode theList = readReverseList( ); printReverseList(theList); }

70 readReverseList( ) static ListNode readReverseList ( ) { int inputval; ListNode front = null; System.out.print("Enter number: "); inputval = (int) NewIO.readNum( ); while ( inputval > 0 ) { front = new ListNode(inputval, front); System.out.print("Enter number: "); inputval = (int) NewIO.readNum( ); } System.out.println( ); return front; }

71 Trace It inputval = sinp.readInt( ); while ( inputval > 0 ) { front = new ListNode(inputval, front); System.out.print("Enter number: "); inputval = NewIO.readNum( ); } null front is null

72 Trace It (1) inputval = sinp.readInt( ); while ( inputval > 0 ) { front = new ListNode(inputval, front); System.out.print("Enter number: "); inputval = NewIO.readNum( ); } null tail 2 value front heap Two things are happening: the use of front (and inputval) to initialize the new node, then the resetting of front to point to the node

73 Trace It (2) inputval = sinp.readInt( ); while ( inputval > 0 ) { front = new ListNode(inputval, front); System.out.print("Enter number: "); inputval = NewIO.readNum( ); } >>>> null tail tail 3 2 value value front heap Two things are happening: the use of front (and inputval) to initialize the new node, then the resetting of front to point to the node

74 Add some more Methods to the ListNode class
Let's add a new method int length ( ) to the ListNode class that computes the length of the list (recursively) class ListNode { private int value; private ListNode tail; public ListNode (int v, ListNode next) { value = v; tail = next; } public int length ( ) { …} public int getValue ( ) { return value; } public ListNode getTail ( ) { return tail; } }

75 It's Easy When You Think Recursively
public int length ( ) { if (tail == null) return 1; else return ( 1 + tail.length( ) ); } We are sending the length message (recursively) to the tail of the current object (i.e., the object pointed to by the current object's tail)

76 Let's Try it Again Let's add another new method String toString ( ) to the ListNode class that prints the elements of the list, separated by commas class ListNode { private int value; private ListNode tail; public ListNode (int v, ListNode next) { value = v; tail = next; } public String toString ( ) { … } public int length ( ) { …} public int getValue ( ) { return value; } public ListNode getTail ( ) { return tail; } }

77 It's Easy When You Think Recursively
public String toString ( ) { String myValue = Integer.toString(value); if (tail == null) return myValue; else return ( myValue + ", " + tail.toString( ) ); } Integer.toString( ) converts an integer to a String object. Normally we wouldn't need to do the conversion manually, except when tail == null and it's the last item in the list.

78 We're Not Done Yet Let's add another new method ListNode nth ( ) to the ListNode class that returns a reference to the nth cell in the list class ListNode { private int value; private ListNode tail; public ListNode (int v, ListNode next) { value = v; tail = next; } public ListNode nth (int n) { … } public String toString ( ) { … } public int length ( ) { …} public int getValue ( ) { return value; } public ListNode getTail ( ) { return tail; } }

79 It's Easy When You Think Recursively
public ListNode nth (int n) { if (n == 0) return this; else if (tail == null) return null; else return tail.nth(n - 1); } If n is 0, we return the head of the list, namely the object that got the message, i.e., "this". If n is not 0, but the tail is null, the list is too short, and I return null. Otherwise, I request the n-1th element from my tail object.

80 Let's Add a Mutating List Operation (alters the list)
Let's add another new, mutating, method void addToEndM (int n) to the ListNode class that adds a new cell (initialized with n) to the end of the list class ListNode { private int value; private ListNode tail; public ListNode (int v, ListNode next) { value = v; tail = next; } public void addToEndM (int n) { … } public ListNode nth (int n) { … } public String toString ( ) { … } }

81 No need to return a value, since it simply alters the end of the list
public void addToEndM (int n) { if (tail != null) // we're a cell in the middle of the list tail.addToEndM(n); else // we're the last cell tail = new ListNode(n, null); } When we're not at the end of the list (that is, tail != null), we just pass the addToEndM(n) message down to our tail object. When we are the last cell, we create a new object, initialize it with n and null, then set our (formerly null) tail to it.

82 OK, One More Mutating List Operation
Let's add one more new, mutating, method ListNode addInorderM (int n) to the ListNode class that adds a new cell (initialized with n) into the list in the correct numerical order (assuming the list was ordered to begin with) Do not insert duplicates If we always use addInorderM to add cells to the list, it will remain ordered

83 No need to return a value, since it simply alters the end of the list
public ListNode addInorderM (int n) { if (n < value) return ( new ListNode(n, this) ); else if (n == value) return this; else if (tail == null) { tail = new ListNode(n, null); return this; } else { tail = tail.addInorderM(n); return this; } }

84 Case Analyis There are four possible situations to consider
They depend on whether we are in the middle of the list or the end of the list They also depend on whether the current cell's value (call it p) compares with the value to be inserted (call it n)

85 Case 1: p is greater than n
if (n < value) return ( new ListNode(n, this) ); We initialize a new node with the value n, point it at the current node ("this"), and return a pointer to it >>>> >>>> >>>> tail tail tail n p value value value

86 Case 2: p equals n else if (n == value) return this; We ignore n, since the problem statement said not to insert duplicates >>>> >>>> tail tail p value value

87 Case 3: p is less than n, but the current object's tail is null
else if (tail == null) { tail = new ListNode(n, null); return this; } We initialize a new node with the value n and the tail null, point the current cell's tail to it, and return a pointer to the current cell >>>> null tail tail p n value value

88 Case 4: p is less than n, and the current object's tail is not null
else { tail = tail.addInorderM(n); return this; } We pass along the call to the current object's tail, set the current object's tail to whatever is returned, and return a reference to the current object >>>> >>>> >>>> tail tail tail p value value value

89 Stacks Stacks: new records added to one end and taken off from the same end; last-in, first-out, LIFO We can talk about the abstract data structure “stack” without knowing anything about the “values” that it stores: Push means “save a value” Pop means “get the value that was saved most recently” Empty means “there are no values to pop”

90 More Stack Operations There are some more primitive operations that might be relevant, depending on how we implement the stack: Remove means “remove all of the stack’s contents” returning space to memory (relevant for pointer-based stack) Full means “there’s no more room to push values” (relevant for an array-based stack)

91 The Stack Name Layer (no commitment as to implementation)
Objects of class DataNode, of stored items, doesn’t have to be defined yet; these are methods of the Stack class: boolean empty ( ) {…} // true if there are no pushed values void push (DataNode newItem) {…} // Add newItem to stack DataNode pop ( ) {…} // Remove the top item from the stack and return it void remove ( ) {…} // Dispose of any current stack contents

92 Question pop, push, etc. are primitives; how would we define, in terms of the primitives, top( ), which gets a copy of the top value of a stack but doesn’t remove that value? We pop the top value, copy it, then push it back onto the stack (assume copyData( ) copies one DataNode object to another): if ( !stack.empty( ) ) { item = stack.pop( ); // Pop the top value… newItem.copyData(item); // …copy it… stack.push(item); // …then push it back onto the stack }

93 The Implementation Layer
Now we have to implement it Pointers are often used to build stacks because (as I said) a linked list can get longer, while arrays are limited to their defined size push pop null <<<< <<<< last last last head First Second Third Data value value value empty A Stack remove

94 Two-class Encapsulation of a Linked List Stack (here's the node class, for inside)
class DataNode { private int value; private DataNode last; public DataNode (int val, DataNode node) { value = val; last = node; } public DataNode getLast( ) { return last; } public void setLast(DataNode node) { last = node; } public int getValue( ) { return value; } public void setValue(int val) { value = val; }

95 The Actual Stack Class class DataStack { private DataNode head;
DataStack ( ) { head = null; } boolean empty ( ) {…} void push (DataNode newItem) {…} DataNode pop ( ) {…} void remove ( ) {…} }

96 The Use of a Backwards Pointer
We defined the DataNode to have a “last” pointer (rather than a “next” one); the pointer will always point to an existing past node: remove push pop null <<<< <<<< last last last head First Second Third Data value value value empty bottom of the stack top of the stack A Stack

97 empty( ) (for class DataStack)
private DataNode head; DataStack( ) { head = null; } boolean empty ( ) { return (head == null); } void push (DataNode newItem) {…} DataNode pop ( ) {…} void remove ( ) {…} }

98 push( ) (for class DataStack)
private DataNode head; DataStack( ) { head = null; } boolean empty ( ) {…} void push (DataNode newItem) { newItem.setLast(head); head = newItem; } DataNode pop ( ) {…} void remove ( ) {…} }

99 pop( ) (for class DataStack)
private DataNode head; … DataNode pop ( ) { if ( empty( ) ) return null; else { DataNode temp = head; head = head.getLast( ); return temp; } } … }

100 remove( ) (for class DataStack)
private DataNode head; DataStack( ) { head = null; } boolean empty ( ) {…} void push (DataNode newItem) {…} DataNode pop ( ) {…} void remove ( ) { head = null; } }

101 Stack Applications One use of a stack is to reverse input:
DataStack stack = new DataStack( ); //create the stack while ( not eof ) { read from user, create a DataNode newItem; stack.push(newItem); } // end the stacking loop while ( !stack.empty( ) ) { // print the stack print stack.pop( ); } // end the unstacking loop

102 Another Stack Application
Another use is to evaluate postfix or Reverse Polish Notation expressions: Infix Postfix (A+ B) * C A B + C * (A – B) / (C * D) A B – C D * / ( (A * (B / C) ) – (D * E) ) A B C / * D E * – Arguments are pushed onto a stack, operators act on the top two popped stack items and push the result onto the stack.

103 The Pseudocode for Postfix Evaluation (no error checking)
while ( not eof ) { read the next data; if data was an operand { create DataNode newItem with data in it; stack.push(newItem); } else it’s an operator, so { termNode1 = stack.pop( ); termNode2 = stack.pop( ); carry out the appropriate operation; create DataNode theResult; stack.push(theResult); } } // end of the while loop remainingTerm = stack.pop( ); print data from remainingTerm;

104 Other Uses of Stacks Method calls
Recursive method calls (delayed evaluation) Delimiter matching Maintenance of free storage space (unused array indexes); order is irrelevant, a stack just holds the information conveniently

105 Easy Question Use our primitives to reverse the order of a stack’s contents, placing the items into another stack

106 Easy Question Use our primitives to reverse the order of originalStack’s contents, placing the items into another stack DataStack copyStack = new DataStack( ); while ( !originalStack.empty( ) ) { copyStack.push(originalStack.pop( )); } // Postcondition: originalStack is empty

107 Queues Queues: new records added to one end and taken off from the other end; first-in, first-out, FIFO We can talk about the abstract data structure “queue” without knowing anything about the “values” that it stores: Enqueue means “save a value” Retrieve means “get the oldest value that remains” Empty means “there are no values in the queue”

108 More Queue Operations There are some more primitive operations that might be relevant, depending on how we implement the queue: Remove means “remove all of the queue’s contents” returning space to memory (relevant for pointer-based queue) FullQ means “the queue can’t hold any more values” (more relevant for an array-based queue)

109 The Queue Name Layer (no commitment as to implementation)
Objects of class DataNode, of stored items, doesn’t have to be defined yet; these are methods of the Queue class: boolean empty ( ) {…} // true if the queue is empty void enqueue (DataNode newItem) {…} // Add newItem to end of the queue DataNode retrieve ( ) {…} // Remove oldest item from the queue and return it void remove ( ) {…} // Dispose of any current queue contents

110 Question enqueue, retrieve, etc. are primitives; how would we define, in terms of the primitives, “nextItem”, which gets a copy of the front value of the queue but doesn’t remove that value?

111 Question enqueue, retrieve, etc. are primitives; how would we define, in terms of the primitives, “nextItem”, which gets a copy of the front value of the queue but doesn’t remove that value? Not so easy. When an item is removed it can only be added back onto the end of the queue. Just to get the value of the first item, we’d need to copy the entire queue. If we really want something like “nextItem”, it should be implemented as a primitive method of the Queue class.

112 The Implementation Layer
Now we have to implement it Pointers are often used to build queues because (as I keep saying) a linked list can get longer, while arrays are limited to their defined size enqueue ? ? retrieve ? ? ? last last last rear front Third Second First Data value value value empty A Queue remove

113 Which of these is better for us?
>>>> >>>> >>>> null front of the line Last Last Last Newest Second Oldest Data value value value rear front null <<<< <<<< front of the line last last last Newest Second Oldest Data value value value rear front

114 First Alternative Adding a node to the rear is easy;
>>>> >>>> >>>> null front of the line Last Last Last Newest Second Oldest Data value value value rear front Adding a node to the rear is easy; Removing a node from the front is hard.

115 Second Alternative Adding a node to the rear is easy;
null <<<< <<<< front of the line last last last Newest Second Oldest Data value value value rear front Adding a node to the rear is easy; Removing a node from the front is also easy!

116 Two-class Encapsulation of a Linked List Queue (here's the node class, for inside)
class DataNode { private int value; private DataNode last; public DataNode (int val, DataNode node) { value = val; last = node; } public DataNode getLast( ) { return last; } public void setLast(DataNode node) { last = node; } public int getValue( ) { return value; } public void setValue(int val) { value = val; }

117 The Actual Queue Class class DataQueue { private DataNode rear, front;
DataQueue ( ) { rear = new DataNode(0, null); front = rear; } boolean empty ( ) {…} void enqueue (DataNode newItem) {…} DataNode retrieve ( ) {…} void remove ( ) {…} }

118 empty( ) (for class DataQueue)
private DataNode rear, front; DataQueue ( ) { rear = new DataNode(0, null); front = rear; } boolean empty ( ) { return (front == rear); } void enqueue (DataNode newItem) {…} DataNode retrieve ( ) {…} void remove ( ) {…} }

119 enqueue( ) (for class DataQueue)
private DataNode rear, front; DataQueue ( ) {…} boolean empty ( ) {…} void enqueue (DataNode newItem) { DataNode temp = new DataNode(0, null); rear.setValue(newItem.getValue( )); rear.setLast(temp); rear = temp; // "advance" rear pointer } // copying newItem's value into queue DataNode retrieve ( ) {…} void remove ( ) {…} }

120 retrieve( ) (for class DataQueue)
private DataNode rear, front; DataNode retrieve ( ) { if ( empty( ) ) return null; else { DataNode temp = front; front = front.getLast( ); return temp; } } }

121 remove( ) (for class DataQueue)
private DataNode rear, front; DataQueue ( ) { rear = new DataNode(0, null); front = rear; } boolean empty ( ) { return (front == rear); } void enqueue (DataNode newItem) {…} DataNode retrieve ( ) {…} void remove ( ) { front = rear; } }

122 Don’t Search Past the End of a Linked List
When searching an input stream, check for not eof When searching an array, watch for the last component When searching a linked list, look for a null-valued pointer // A loop with a potential bug—sought might not be there current = head; // Start current at head of the list while ( current.getValue( ) != sought) { current = current.getNext( ); }

123 Better, but Still Not Necessarily Correct
//A possibly correct, but probably buggy, version of the // same loop current = head; // Start current at head of the list // What precondition has to exist here, before the loop? while ( (current.getValue( ) != sought) && (current.getNext( ) != null) ) { current = current.getNext( ); } //Postcondition: if sought is there, current addresses it if ( current.getValue( ) == sought ) System.out.println("Found the value."); else System.out.println("Did not find the value.");

124 Another Version, Maybe Safer
// A different version of the same loop searching = true; //Use an auxiliary boolean variable current = head; //Start current at head of the list // Now, current might be null while ( (current != null) && searching ) { if (current.getValue( ) == sought) searching = false; // since we’ve found it else current = current.getNext( ); } // Postcondition: if current isn’t null, it addresses sought if ( current != null ) System.out.println("Found the value."); else System.out.println("Did not find the value.");

125 Trees A tree is another data structure that can be built using pointers It can be defined recursively: a tree is a node that’s linked to one or more trees, or to nothing. Branches lead to finer branches, but never lead back to the root. Subtrees must be distinct (no two trees share the same node).

126 Terminology The root of a tree is the first (top) node
The nodes an element points to are its children; it is the parent A node with no children is called a leaf root parent child leaf

127 Binary Tree A tree whose nodes have at most two children is called a binary tree. class BinaryNode { ProblemData data; BinaryNode left, right; } BinaryNode current;

128 Recursive Tree Searching (one method)
If current’s left child isn’t null, point current at the left child and search the (sub)tree. If current’s right child isn’t null, point current at the right child and search the (sub)tree. Print the value stored in the current node. Using recursion allows backtracking without backward pointers. Goal: Print every node’s stored value. Stacking Plan: Visit the left subtree. Visit the right subtree. Bound: Reaching a leaf, or node that has no subtrees. Unstacking Plan: Print the current node’s stored value.

129 The Java Code (acting at the BinaryNode level)
void inspectTree (BinaryNode current) { // Visits every node of a non-empty binary tree if ( current.left != null ) inspectTree(current.left); if ( current.right != null ) inspectTree(current.right); printProblemData(current.data); } // inspectTree

130 Using inspectTree — Postorder
+ / * + A D B C E F inspectTree searches the tree in postorder: A B C + / D E F – * + Postfix notation and reverse Polish notation are other names for this (as we’ve seen).

131 Preorder Search First variation: Preorder search: + * – +
/ * + A D B C E F First variation: Preorder search: printProblemData(current.data); if (current.left != null) inspectTree(current.left); if (current.right != null) inspectTree(current.right); Search then goes as: + / A + B C * D – E F

132 Inorder Search Second variation: Inorder search: + * – +
/ * + A D B C E F Second variation: Inorder search: if (current.left != null) inspectTree(current.left); printProblemData(current.data); if (current.right != null) inspectTree(current.right); Search then goes as: A / B + C + D * E – F

133 The Type Definition class CodeNode { char letter; CodeNode dot, dash;
} CodeNode root;

134 Binary Search Tree a root b d c e f leaves Definitions:
* The root of a tree is the only node which doesn’t have a father node. * A leaf is a node which doesn’t have any son nodes. * A binary tree is a tree whose nodes have at most two son nodes. * A binary search tree is: 1. A binary tree; 2. All the nodes which are descendents of the right son of a specific node including the right son itself have values greater or equal to the value in the node; 3. All the nodes which are descendents of the left son of a specific node including the left son itself have values less than the value in the node. a root b In the example: b,c,d,e,f > a b > d,e,f c > b d c e f leaves

135 Binary Tree Node public class Node { protected int _data;
protected Node _left,_right; public Node(int data) { _data = data; _left = _right = null; } public void addRight(Node node) { _right = node; public void addLeft(Node node) { _left = node; public Node getRight() { return _right; } public Node getLeft() { return _left; public int getData() { return _data;

136 Binary Search Tree Implementation
public class BinTree { protected Node _root; protected int _size; public BinTree() { _size = 0; } public void add(int data) { add(data,_root,_root); _size++;

137 Implementation (continued); Recursive add method
private void add(int data, Node son, Node father) { //stop the recursion, we have reached a leaf if (son == null) { if (father == null) //this leaf is the root _root = new Node(data); else { //just a regular leaf if (father.getData() >data) father.addLeft(new Node(data)); else father.addRight(new Node(data)); } else { if (son.getData() > data) add(data, son.getLeft(), son); else add(data, son.getRight(), son);

138 Implementation (continued)
/** * Recursive method: * Traversal of the tree (inorder). */ private void traverse(Node node) { if (node != null) { traverse(node.getLeft()); System.out.println(node.getData()); traverse(node.getRight()); }

139 Implementation (continued)
What's the result of this main: public static void main(String args[]) { BinTree myTree = new BinTree(); myTree.add(7); myTree.add(1); myTree.add(3); myTree.add(2); myTree.add(4); myTree.add(5); myTree.add(8); myTree.add(6); myTree.traverse(myTree._root); } The result : 1 2 : 8 The numbers are sorted!!!

140 Binary search tree of words
gregor awoke samsa a discover been giant cockroach one to transformed morning only he had into

141 InOrder Traversal a awoke been cockroach discover giant gregor had he into morning one only samsa to transformed gregor awoke samsa a discover been giant cockroach one to transformed morning only he had into


Download ppt "*Basic Link Operations *Queues, Stack, Trees"

Similar presentations


Ads by Google