**Linked Lists** Contents • LinkedList implements the Interface List • Doubly Linked List implementation of common methods • boolean add( Object x) -- append to end of the list • boolean add(int i, Object x) – insert at position i • boolean remove(int i) – remove object at position i • Singly Linked List -- outline of methods • Circularly Linked List

**Linked Lists** A LinkedList implements the interface List There are a number of ways in which a LinkedList can be implemented internally, but each implementation should provide the client (code that uses a LinkedList) with a single common set of operations that can be evoked by messages to the LinkedList object. Types of LinkedList implementations include: • Doubly linked list • Singly linked list • Circular-linked list We will examine how the main List operations are implemented in each of these alternatives

**Linked Lists** Doubly-linked List A LinkedList is a connected sequence of Nodes. It is composed of two classes of objects: LinkedLists and Nodes. class Node { //Node methods go here //attributes protected Node pred, succ; public Object data; } class LinkedList implements List { //class Node (see left) is declared here //implementation of List methods goes here //attributes private Node head, tail; privateint size; } Node is an internal class visible only to LinkedList objects. The protected attributes: pred and succ, have file scope and are thus directly accessible to the methods in class LinkedList

**p** pred pred data data succ succ Linked Lists Useful terminology for referring to Nodes in a LinkedList Nodes are not named objects, but are referred to by a “pointer” Node p = new Node(theObject); p.succ = new Node(nextObject); This is the the Node that p points to This Node is the successor of the Node that p points to

**aList** head size tail p p 24 21 Linked Lists LinkedList aList = new LinkedList( ); Integer temp = new Integer(21); Node p = new Node(temp); Integer temp = new Integer(24); Node p = new Node (temp); aList.add( new Integer(24) ); aList.add( new Integer(21) ); //head != 0 tail.succ = p; if (head == 0) head = p; tail = p; size++; p.pred = tail; tail = p; size++; 1 0 2

**Linked Lists** Putting it together publicboolean add (Object theObj) { Node p = new Node(theObj); if (head == 0) head = p; else { tail.succ = p; p.pred = tail; } tail = p; size++; return true; }

**aList** head size tail 10 21 24 p 3 Linked Lists Inserting an object at position i Integertemp = new Integer (3); Node p = new Node(temp); p.pred = 0; p.succ = head; if (head != 0) head.pred = p; 3 4 head = p; size++; Insert at front of the list (i == 0) The successor of Node referenced by p is Node referenced by head else (head ==0) -- inserting into an empty list -- set tail = p

**aList** head size tail 10 21 24 p 41 Linked Lists Inserting an object at position i Integertemp = new Integer (3); Node p = new Node(temp); if (i == size) { //insert at end p.pred = tail; p.succ = 0; tail.succ = p; 3 4 tail = p; size++; Inserting at end of non-empty list (i==size) p’ s predecessor is the Node tail points to Make Node p points to the successor of Node tail points to The Node p points to is now at the end of the list

**aList** head size tail q q q 10 21 24 p 23 Linked Lists Integertemp = new Integer (3); Node p = new Node(temp); Inserting an object at position i int count = 0; Node q = head; while (count < i) { count++; q = q.getNext( ); } 3 4 p.pred = q.getPrev( )); Inserting at general position – (0 <= i < size) count = 0 count = 1 p.succ = q; count = 2 q.getPrev( ).succ = p; //3 The order of these statements is important – statement 3 MUST precede statement 4. Move a handle to the Node at position i – Let i = 2 in this example Insert new Node before the Node that q points to. q.pred = p; //4 size++;

**else { //insert at general position** int count = 0; Node q = head; while (count < i) { count++; q = q.getNext( ); } p.pred = q.getPrev( ); p.succ = q; q.getPrev( ).succ = p; q.pred = p; } size++; return true; q.getPrev( ) returns a reference to the previous Node – Make the successor of that Node = p. } Linked Lists Putting it all together publicboolean add(int i, Object x) { if (i < 0 || i > size) { //range error System.err.println (“error – index out of range”); System.exit(1); //better – throw Exception } Node p = new Node(x); if (i ==0) { //insert at front p.pred = 0; //superfluous p.succ = head; if (head !=0) head.pred = p; else tail = p; head = p; } elseif (i == size) { //insert at end p.succ = 0; p.pred = tail; tail.succ = p; tail = p; }

**aList** head size tail p 41 21 24 Linked Lists Removing objects from a List Node p = head; if (i ==0) { //remove first Node head = p.getNext( ); if (head != 0) head.pred = 0; else //removing last node tail = 0; size--; } 3 2 Remove first Node – (i == 0) Automatic garbage collection reclaims the unreferenced Node when p goes out of scope.

**aList** head size tail p 41 21 24 Linked Lists if (i ==size-1) { //remove last Node p = tail; //Node * p; set previously if (head != tail) { tail.getPrev().succ = 0; tail = tail.getPrev( ); } else {//removing last node tail = 0; head = 0; } size--; } Removing objects from a List 3 2 Remove the last node – (i == size – 1) tail.getPrev( ) Automatic garbage collection reclaims memory when p goes out of scope

**aList** head size tail p p 41 21 24 Linked Lists Removing objects from a List Node p = head; int pos = 0; while (pos < i) { //find node to cut p = p.getNext( ); //move handle pos++; } p.getPrev( ).succ = p.succ; p.getNext( ).pred = p.pred; size--; } 3 2 p.getPrev( ) p.getNext( ) The Node referenced by p is deleted when p goes out of scope pos = 0 pos = 1 Remove Node in general position – ( i ==1)

**Linked Lists** Bringing it all back home elseif (i == size-1) { //remove last node p = tail; if (head != tail) { tail.getPrev.succ = 0; tail = tail.getPrev( ); } else { head = 0; tail = 0; } } //end else if else { //remove Node in general position p = head; int pos = 0; while (pos < i ) { //move handle p = p.getNext( ); pos++ } p.getPrev.succ = p.succ; p.getNext.pred = p.pred; } //end else p.setPrev(0); p.setNext(0); //for safety size--; return true; publicboolean remove(int i) { if (i < 0 || i >= size) { //range error System.err.println (“error – index out of range”); System.exit(1); } Node p; if (i == 0 ) // remove first node p = head; head = p.succ; if (head != 0) head.pred = 0; else tail = 0; } //end if } //end remove

**aList** size head tail p q p q p Linked Lists publicclass Node { public Node(Object x) {…} publicvoid setNext( ) {…} public Node getNext( ) {…} public Object getData( ) {…} private Node succ; private Object data; } Singly-linked Lists 3 data succ 21 24 47 pos = 0 pos =2 pos = 1 Implementing methods add( ) and remove( ) will be left as an exercise. To remove the Node at index pos, remove the Node that p references. Use the Node that q references to reattach the links. Move two handles in sequence until p reaches position i – (let i = 2) for(int pos = 0; pos < i; pos++) { q = p; p = p.getNext( ); } To perform an insert at pos, insert the new Node after the Node that q references and before the Node that p references Node p = head, q = head;

**aList** size head Linked Lists Circularly Linked Lists 3 21 24 47 A circularly-linked list is a singly-linked list where the last Node refers back to the first Node in the list. A tail reference is not used.

**aList** size head p q q p p Linked Lists Traversing a circularly-linked list To traverse a circularly-linked list, move a pair of handles until pos == i (or p.getNext( ) == head) An insertion can be performed after the Node that q references, and a removal will remove the Node referenced by p, using q to reattach the list. Locate the node containing x = 47 3 21 24 47 Node p = head, q; while (p.getNext( ) != head && !p.getData( ).equals(x)) { q = p; p = p.getNext( ); }

**aList** size head Linked Lists A circularly-linked list with a single Node Special case – List contains a single Node The succ field of a single Node contains a handle to itself 1 Constructor for Node public Node(Object obj) { data = obj; succ = this; } 21 The object under construction The only special circumstances about adding the first or removing the last Node from a circularly-linked list involve setting the contents of head. Create a Node referring to itself and overwrite the succ field using setNext( ) when adding to the list if Node is not the first Node to be added.