430 likes | 453 Views
Learn about linked data structures, singly linked lists, and how to implement them in Java for efficient data management. Develop a deeper understanding of node definitions, adding nodes, and enhancing object-oriented principles.
E N D
Linked lists • Linked data structure = capsules of data (nodes) that are connected via links • (Singly) linked list = linear structure of nodes connected via a single link to the next element • First node is called the head node • Last node is called the tail node
Linked lists • A (link or next) value of null is typically used to represent the end of the list. • An empty list is one that starts with a null value (the head is null).
Integer node definition public class Node { private int mData; Node mNext; //AKA link //next, we need a ctor(s) } What access is this?
Integer node definition public class Node { private int mData; private Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } } Why don’t we have a no-arg ctor? What does an empty list look like?
Add a node to the beginning of the list public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } } public class Main { public static void main ( String args[] ) { Node head = null; Node n = new Node( 13 ); //add at beginning n.mNext = head; head = n; } }
Add another node to the beginning of the list public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } } public class Main { public static void main ( String args[] ) { Node head = null; Node n = new Node( 13 ); //add at beginning n.mNext = head; head = n; n = new Node( 12 ); //add at beginning n.mNext = head; head = n; } } Can you draw a picture of these data structures in memory?
Add a toString method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } }
Add a toString method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData; } } public class Main { public static void main ( String args[] ) { Node head = null; Node n = new Node( 13 ); //add at beginning n.mNext = head; head = n; n = new Node( 12 ); //add at beginning n.mNext = head; head = n; System.out.println( head ); } } Why is this necessary?
Add a toString method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class Main { public static void main ( String args[] ) { Node head = null; Node n = new Node( 13 ); //add at beginning n.mNext = head; head = n; n = new Node( 12 ); //add at beginning n.mNext = head; head = n; System.out.println( head ); } } Something interesting happens! What?
How can we make this more OO? public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class Main { public static void main ( String args[] ) { Node head = null; Node n = new Node( 13 ); //add at beginning n.mNext = head; head = n; n = new Node( 12 ); //add at beginning n.mNext = head; head = n; System.out.println( head ); } }
How can we make this more OO? public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class MyLinkedList { private Node mHead = null; } public class Main { public static void main ( String args[] ) { MyLinkedList mml = new MyLinkedList(); } } //end class Main
Add a toString method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class MyLinkedList { private Node mHead = null; public String toString ( ) { return “” + mHead; } } public class Main { public static void main ( String args[] ) { MyLinkedList mml = new MyLinkedList(); } } //end class Main
Next, let’s add an add method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class MyLinkedList { private Node mHead = null; public void add ( int n ) { … } public void add ( Node n ) { … } public String toString ( ) { return “” + mHead; } }
Next, let’s add an add method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class MyLinkedList { private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } public void add ( Node n ) { … } public String toString ( ) { return “” + mHead; } } Any potential privacy leak?
Next, let’s add an add method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class MyLinkedList { private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } public void add ( Node n ) { n.mNext = mHead; mHead = n; } public String toString ( ) { return “” + mHead; } } Any potential privacy leak?
Next, let’s add an add method public class Node { private int mData; Node mNext; //ctor public Node ( int value ) { mData = value; mNext = null; } //accessor public int getData ( ) { return mData; } public String toString ( ) { return "" + mData + “ ” + mNext; } } public class MyLinkedList { private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } public void add ( Node n ) { n = new Node( n.getData() ); n.mNext = mHead; mHead = n; } public String toString ( ) { return “” + mHead; } } Corrected potential privacy leak.
Precondtion(s) public class MyLinkedList { private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } public void add ( Node n ) { n = new Node( n.getData() ); n.mNext = mHead; mHead = n; } public String toString ( ) { return “” + mHead; } } What precondition is important here?
Analysis of algorithm – computational complexity public class MyLinkedList { private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } public void add ( Node n ) { n = new Node( n.getData() ); n.mNext = mHead; mHead = n; } public String toString ( ) { return “” + mHead; } } Is either add method dependent on the current size of the list?
Add to the tail of the list public class MyLinkedList { private Node mHead = null; public void addTail ( Node n ) { if (mHead==null) { … } else { … } } … }
Add to the tail of the list public class MyLinkedList { private Node mHead = null; public void addTail ( Node n ) { if (mHead==null) { n.mNext = null; mHead = n; } else { … } } … }
Add to the tail of the list public class MyLinkedList { private Node mHead = null; public void addTail ( Node n ) { if (mHead==null) { n.mNext = null; mHead = n; } else { Node temp = mHead; while (temp.mNext!=null) { temp = temp.mNext; } n.mNext = null; temp.mNext = n; } } … } Is the addTail method dependent on the current size of the list? Convert this while-loop to a for-loop.
Linked list • The linked list is so useful that Sun has provided us with one! • See http://java.sun.com/j2se/1.5.0/docs/api/java/util/LinkedList.html • There is also a List interface. • See http://java.sun.com/j2se/1.5.0/docs/api/java/util/List.html
Example of creating a linked list • Other useful functions: • void clear ( ) • Removes all of the elements from this list. • boolean contains ( Object o ) • Returns true if this list contains the specified element. • E get ( int index ) • Returns the element at the specified position in this list.
Example of creating a linked list • Other useful functions: • E remove ( int index ) • Removes the element at the specified position in this list. • boolean remove ( Object o ) • Removes the first occurrence in this list of the specified element. • int size ( ) • Returns the number of elements in this list.
Example of creating a linked list • Other useful functions: • void add ( int index, E element ) • Inserts the specified element at the specified position in this list. • E set ( int index, E element ) • Replaces the element at the specified position in this list with the specified element. • boolean isEmpty ( ) • Returns true if this list contains no elements.
Variations on a theme (different types of lists) • Singly linked • Circular
Variations on a theme (different types of lists) • Doubly linked
Our linked list and an inner class • Often the user doesn’t need to know about the Node class. • Let’s modify MyLinkedList to use an inner class for the Node.
Our linked list and an inner class public class MyLinkedList2 { // - - - - - - - - - private class Node { private int mData; private Node mNext; public Node ( int value ) { //ctor mData = value; mNext = null; } public String toString ( ) { return "" + mData + " " + mNext; } } //end class Node // - - - - - - - - - private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } public void addTail ( int value ) { Node n = new Node( value ); if (mHead==null) { n.mNext = null; mHead = n; } else { Node temp = mHead; while (temp.mNext!=null) { temp = temp.mNext; } n.mNext = null; temp.mNext = n; } } public String toString ( ) { return "" + mHead; } } //end class MyLinkedList2
Our linked list and an inner class public class MyLinkedList2 { // - - - - - - - - - private class Node { private int mData; private Node mNext; public Node ( int value ) { //ctor mData = value; mNext = null; } public String toString ( ) { return "" + mData + " " + mNext; } } //end class Node // - - - - - - - - - private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } … public int removeHead ( ) { ? } … public String toString ( ) { return "" + mHead; } } //end class MyLinkedList2
Our linked list and an inner class public class MyLinkedList2 { // - - - - - - - - - private class Node { private int mData; private Node mNext; public Node ( int value ) { //ctor mData = value; mNext = null; } public String toString ( ) { return "" + mData + " " + mNext; } } //end class Node // - - - - - - - - - private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } … public int removeHead ( ) { int temp = mHead.mData; mHead = mHead.mNext; return temp; } … public String toString ( ) { return "" + mHead; } } //end class MyLinkedList2 But wait! How can we access these private members?
Finally, how can we convert it to a generic? public class MyLinkedList2 { // - - - - - - - - - private class Node { private int mData; private Node mNext; public Node ( int value ) { //ctor mData = value; mNext = null; } public String toString ( ) { return "" + mData + " " + mNext; } } //end class Node // - - - - - - - - - private Node mHead = null; public void add ( int n ) { Node temp = new Node( n ); temp.mNext = mHead; mHead = temp; } public void addTail ( int value ) { Node n = new Node( value ); if (mHead==null) { n.mNext = null; mHead = n; } else { Node temp = mHead; while (temp.mNext!=null) { temp = temp.mNext; } n.mNext = null; temp.mNext = n; } } public String toString ( ) { return "" + mHead; } } //end class MyLinkedList2
Finally, how can we convert it to a generic? public class MyLinkedList3<T> { private class Node<T> { private T mData; private Node<T> mNext; public Node ( T value ) { //ctor mData = value; mNext = null; } public String toString ( ) { return "" + mData + " " + mNext; } } //end class Node private Node<T> mHead = null; public void add ( T n ) { Node<T> temp = new Node<T>( n ); temp.mNext = mHead; mHead = temp; } public void addTail ( T value ) { Node<T> n = new Node<T>( value ); if (mHead==null) { n.mNext = null; mHead = n; } else { Node<T> temp = mHead; while (temp.mNext!=null) { temp = temp.mNext; } n.mNext = null; temp.mNext = n; } } public T removeHead ( ) {T temp = mHead.mData; mHead = mHead.mNext; return temp; } public String toString ( ) { return "" + mHead; }} //end class MyLinkedList3
Using our generic, MyLinkedList3<T> MyLinkedList3<Integer> mml3 = new MyLinkedList3<Integer>(); mml3.add( 192 ); System.out.println( mml3 );
Stack • A stack is a data structure with the major operations of: • push – adds an item to the head • pop – removes an item from the head • isEmpty – true when the stack is empty; false otherwise • A stack is also described as a LIFO (Last In, First Out)
Queue • A queue is a data structure with the major operations of: • enq (enqueue) – adds an item to the tail • deq (dequeue) – removes an item from the head • isEmpty – true when the queue is empty; false otherwise • A queue is also described as a FIFO (First In, First Out)
Sets • “A set is a collection of elements in which order and multiplicity are ignored.” • (Note: Bags or multisets may have duplicate elements.) • A simple implementation of sets is a linked list.
Set operations • Add elements – add a new item (an item that does not already exist) into a set • Contains – determine if a target item is a member of the set • Union – return a set that is the union (a new set of items from either set) of two sets • Intersection – return a set that is the intersection (a new set where each item is contained in both sets) of two sets • Given a particular set implementation, can you determine O (big-oh) for each operation?
Additional set operations • An iterator so that every item can be retrieved from a set • Remove an item from the set • Obtain the cardinality (the number of items in the set) of the set • Given a particular set implementation, can you determine O (big-oh) for each operation?