1
M180: Data Structures & Algorithms in Java
Linked Lists
Arab Open University
Outline• Linked list nodes• Linked list operations
– Insertion– Append– Deletion
• Other types of linked lists– Doubly-linked– Circular
Limitation of Arrays
• An array has a limited number of elements– routines inserting a new value have to check that there
is room
• Can partially solve this problem by reallocating the array as needed (how much memory to add?)– adding one element at a time could be costly– one approach - double the current size of the array
• A better approach: use a Linked List
Dynamically Allocating Elements
• Allocate elements one at a time as needed, have each element keep track of the next element
• Result is referred to as linked list of elements, track next element with a pointer
Array of Elements in Memory
Linked List
Jane AnneBob
Jane Anne Bob
5
Anatomy of a linked list• A linked list consists of:
– A sequence of nodes
a b c d
Each node contains a valueand a link (reference) to some other node
The last node contains a null link
The list may have a header
myList
6
More terminology• A node’s successor is the next node in the sequence
– The last node has no successor• A node’s predecessor is the previous node in the
sequence– The first node has no predecessor
• A list’s length is the number of elements in it– A list may be empty (contain no elements)
ListNode
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 next ListNode 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.
A0 A1 A2 A3first ListNode ListNodeListNode
ListNode: Definitionpublic 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
Linked List: Insertion
• Insert X immediately after current position
a
current
current
b c d
b c d
x
Implementing Insertion: Step By Step• Insertion immediately after current position
// create a new node
tmp = new ListNode<DataType>();
a
current
b
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;
a
current
b
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;
a
current
b
tmp
x
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;
a
current
b
tmp
x
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;
a
current
b
tmp
x
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;
a
current
b
tmp
x
• Insert X immediately at the end of the list // last refers to the last node in the linked listlast.next = new ListNode<DataType>();last = last.next; // adjust lastlast.data = x; // place x in the nodelast.next = null; // adjust next
• Most efficient approachlast = last.next = new ListNode (x, null);
Implementing Append
a b c d
last
a b c X
last
d
Implementing Basic Deletion• Delete an item immediately after current position
• Basic deletion is a bypass in the linked list.
a b x
a b
current
current
current.next = current.next.next;
Implementing Basic Deletion
• Need a reference to node prior to the one to be deleted.
a b x
a b x
a b
current
current
current
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);
A0 A1 A2 A3
first
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); ...}
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, set current to header.next;
– List is empty if header.next == null;• Searching routines will skip header.
A1 A2 A3
header
Representing the “current” position
• How do we specify where an operation should occur?– Index position (int?)– ListNode
// Methodsvoid 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, ListNode current);
a x
current
List Iterator Class• Maintains a notion of the current position• 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: Implementationpublic 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: Implementationpublic 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) {???}}
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• 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()); } }}
• 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.
Other Linked Lists
A
head tail
prev
next
A B C
first
prev
next
Doubly-linked lists: Wrong InsertNext
newNode = new DoublyLinkedListNode ( x );
1 newNode.prev = current;2 newNode.prev.next = newNode;
……
x
ba
1
2
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;
A B
current
X
prev
next
newNode
1
3
2 5
4
6
Doubly-linked lists: DeleteCurrent
1.current.prev.next = current.next;2.current.next.prev = current.prev;3.current = current.prev;
x
ba
current
1
23
34
DLLs compared to SLLs
• Advantages:– Can be traversed in either
direction (may be essential for some programs)
– Some operations, such as deletion and inserting before a node, become easier
• Disadvantages:– Requires more space– List manipulations are slower
(because more links must be changed)
– Greater chance of having bugs (because more links must be manipulated)