410 likes | 502 Views
Implementation Of Linked-Lists. Outline. Linked list nodes Linked list operations Insertion Append Deletion Linked list representation & implementation Other types of linked lists Sorted Doubly-linked Circular. ListNode. ListNode. ListNode. ListNode. A0. A1. A2. A3. first.
E N D
Outline • Linked list nodes • Linked list operations • Insertion • Append • Deletion • Linked list representation & implementation • Other types of linked lists • Sorted • Doubly-linked • Circular
ListNode ListNode ListNode ListNode A0 A1 A2 A3 first Linked Lists • Stores a collection of items non-contiguously. • Each item in the list is stored with an indication of where the next item is. • Must know where first item is. • The list will be a chain of objects, called nodes, of type ListNode that contain the data and a reference to the nextListNode in the list. • Allows addition or deletion of items in the middle of collection with only a constant amount of data movement. Contrast this with array.
ListNode: Definition public class ListNode <DataType> { DataType data; ListNode<DataType> next; // constructors ListNode(DataType d, ListNode<DataType> n) { data = d; next = n; } ListNode(DataType d) { this (d, null); } ListNode() { this (null); } }
a a b c d b c d x current Linked List: Insertion • Insert X immediately after current position current
a b current tmp Implementing Insertion: Step By Step • Insertion immediately after current position // create a new node tmp = new ListNode<DataType>();
a b current tmp Implementing Insertion: Step By Step • Insertion immediately after current position // create a new node tmp = new ListNode<DataType>(); // place x in the element field tmp.data = x; x
a b current tmp Implementing Insertion: Step By Step • Insertion immediately after current position // create a new node tmp = new ListNode<DataType>(); // place x in the element field tmp.data = x; // x’s next node is b tmp.next = current.next; x
a b current tmp Implementing Insertion: Step By Step • Insertion immediately after current position // create a new node tmp = new ListNode<DataType>(); // place x in the element field tmp.data = x; // x’s next node is b tmp.next = current.next; // a’s next node is x current.next = tmp; x
a b current tmp Implementing Insertion: Shorter Version • A shorter version: // create a new node tmp = new ListNode<DataType>(x,current.next); // a’s next node is x current.next = tmp; x
a b current tmp Implementing Insertion: Shorter Version • A shorter version: // create a new node tmp = new ListNode<DataType>(x,current.next); // a’s next node is x current.next = tmp; x
a b current Implementing Insertion: Shortest Version • An even shorter version: // create a new node current.next = new ListNode<DataType>(x,current.next); x
a b c d a b c d X last last Implementing Append • Insert X immediately at the end of the list // last refers to the last node in the linked list last.next = new ListNode<DataType>(); last = last.next; // adjust last last.data = x; // place x in the node last.next = null; // adjust next • Most efficient approach last = last.next = new ListNode (x, null); last last
a b x a b current current Implementing Basic Deletion • Delete an item immediately after current position • Basic deletion is a bypass in the linked list.
a b x a b x current current current a b Implementing Basic Deletion • Need a reference to node prior to the one to be deleted. current.next = current.next.next;
Important Note • Remember!!! • What we store in a ListNode is a reference to the object, NOT the objectitself nor a copy of theobject!
A0 A1 A2 A3 first Iterate Through The Linked List • If items are stored in contiguous array: //step through array, outputting each item for (int index = 0; index < a.length; index++) System.out.println (a[index]); • If items are stored in a linked list: // step through list, outputting each item for(ListNode p=l.first; p!=null; p=p.next) System.out.println (p.data);
Implementing a Linked List • So what would a Linked List implementation look like? • What happens if we want to • Delete the first item? • Insert an item before the first item? class MyLinkedList <DataType> { // Field ListNode<DataType> first; // Methods void insert(DataType x, ???); void delete(DataType x, ???); void append(DataType x); ... }
A1 A2 A3 header Header Nodes • Deletion of first item and insertion of new first item are special cases. • Can be avoided by using header node; • contains no data, but serves to ensure that first "real" node in linked has a predecessor. • To go to the first element, setcurrent to header.next; • List is empty if header.next == null; • Searching routines will skip header.
a x current Representing the “current” position • How do we specify where an operation should occur? • Index position (int?) • ListNode // Methods void insert(DataType x, ???); void delete(DataType x, ???); void insert(DataType x, int current); void delete(DataType x, int current); void insert(DataType x, ListNode current); void delete(DataType x, ListNodecurrent);
List Iterator Class • Maintains a notion of the current position (aka cursor). • The List class provides methods that do not depend on any position (such as isEmpty, and makeEmpty). • A List iterator (ListItr) provides other methods such which act on the current position stored in the iterator: • next() / advance() • hasNext() / isValid() • retrieve()
Linked List Iterator: Implementation public class ListItr <DataType> { ListNode<DataType> current; // Current position ListItr(ListNode<DataType> node) { } public boolean hasNext() { } public void next() { } public DataType retrieve() { } }
Example Usage • A method that computes the number of elements in any list: public static int listSize (List theList) { int size = 0; ListItr itr; for(itr=theList.first();itr.hasNext();itr.next()) size++; return size; }
Linked Lists: Implementation public class List <T> { // Header node private ListNode<T> header; // Check if list is empty boolean isEmpty() {???} // Make the list empty void makeEmpty () {???} // Cursor to header node public ListItr<T> zeroth() {???} // Cursor to first node public ListItr<T> first() {???} // Cursor to (first) node containing x public ListItr<T> find(T x) {???} // Cursor to node before node containing x public ListItr<T> findPrevious(T x) {???} // Insert x after current cursor position public void insert(T x, ListItr<T> current) {???} // Remove (first) node containing x public void remove(T x) {???} }
Java Implementations • Mostly straightforward; all routines are short. • ListItr maintains a reference to the list that it is bound to as a private data member. • Because ListItr is in the same package as List, if List's data access is (package) friendly, it can be accessed by ListItr.
Note on Exceptions • Some routines throw ItemNotFound exceptions. • However, do not overuse exceptions, because they must always be caught or propagated. As an example, advance does not throw an exception, even if we have already advanced past the end. Otherwise, listSize would need a try/catch block.
Linked List Properties • Running Time Analysis • insert next, prepend - O(1) • delete next, delete first - O(1) • find - O(n) • retrieve current position - O(1) • Advantages • Growable (compared to array) • Easy (quick) in read/insert/delete the first and the last element (if we also store the last position not just the head/current position) • Disadvantages • Calling to operator new (compare to array) • overhead one reference for each node
Print all elements of Linked List • Method 1: Without Iterator, Simple Looping public class LinkedList <T> { public void print() { // step through list, outputting each item ListNode<T> p = header.next; while (p != null) { System.out.println (p.data); p = p.next; } } }
Print all elements of Linked List(2) • Method 2: Without Iterator, Using Recursion public class LinkedList <T> { private void printRec (ListNode<T> node) { if (node != null) { System.out.println (node.data); printRec (node.next); } } public void print () {printRec (header.next);} }
Print all elements of Linked List(3) • Method 3: Recursion class ListNode <T> { public void print () { System.out.println (data); if (next != null) next.print (); } } class LinkedList <T> { public void print() { if (header.next != null) header.next.print (); } }
Print all elements of Linked List(4) • Method 4: Using iterator class LinkedList <T> { public void print() { ListItr<ListNode<T>> itr = first(); while(itr.hasNext()) { itr.next(); System.out.println(itr.retrieve()); } } }
Sorted Linked Lists • Maintains items in sorted order. • Almost all operations are the same as linked lists, except for insert. • In fact, a sorted linked list IS-A linked list, suggesting that inheritance may be used. Extend a SortListItr from ListItr. • However, items in a sorted linked list should be Comparable.
Simple Implementation • Use inheritance, and create Insert method public void insert( Comparable X ) • Note however, that in this implementation, we have no assurance that the list is sorted, because it can be accessed by either a SortListItr or a ListItr. • See the textbook for details.
Important Note • ListItr used the equals member function in find and remove. • Must make sure MyInteger has an equals member function if we are storing a linked list of MyIntegers. • Signature MUST BE public boolean equals( Object Rhs ) • The following signature is wrong! public boolean equals( Comparable Rhs ) • If you try it, the method from class Object will be inherited and used: public boolean equals (Object obj) { return (this == obj); }
prev A next head tail prev A B C next first Other Linked Lists • Doubly-linked lists: Each list node stores both the previous and next nodes in the list. Useful for traversing linked lists in both directions. • Circular-linked lists: Last node's next references the first node. Works with or without headers.
b a x Doubly-linked lists: Wrong InsertNext newNode = new DoublyLinkedListNode ( x ); 1 newNode.prev = current; 2 newNode.prev.next = newNode; … … 2 1
A B 4 3 prev 2 5 X next current 1 6 newNode Doubly-linked lists: insertNext 1 newNode = new DoublyLinkedListNode (x); 2 newNode.prev = current; 3 newNode.next = current.next; 4 newNode.prev.next = newNode; 5 newNode.next.prev = newNode; 6 current = newNode;
1 a b 2 3 x current Doubly-linked lists: DeleteCurrent • current.prev.next = current.next; • current.next.prev = current.prev; • current = current.prev;
JDK: package java.util • Collection - List - LinkedList • Iterator - ListIterator
Summary • ListNode • List, LinkedList • Iterator class • a class that maintains a current position and performs all routines that depend on knowing the position in the list. • Advantage & Disadvantage of linked list • Growable • Overhead a pointer, new operator • Sequential access only
Further Reading • Find and study available data structure in Java API:http://telaga.cs.ui.ac.id/WebKuliah/java5/docs/api/java/util/package-summary.html • Generics in Java 2 SE 5:http://telaga.cs.ui.ac.id/WebKuliah/java5/Java5-Generics.pdf • Chapter 6 & 17