Personal tools
You are here: Home Classes Fall 2004 - Spring 2005 Old CS 160 Lecture 9 -- Linked Lists
Navigation
Log in


Forgot your password?
« May 2008 »
Su Mo Tu We Th Fr Sa
123
456789 10
11121314151617
18192021222324
25262728293031
 
Document Actions

Lecture 9 -- Linked Lists

by admin last modified 2005-05-25 15:41

Linked Lists

Consider the array implementation of List.  It provides efficient access to individual data items by index; in particular, the get and set methods are fast.  However, it has some shortcomings:
  • The resize operation is expensive (in execution time).
  • Adding at the beginning or middle of the list is expensive.
  • Removing from the beginning or middle of the list is expensive.
These characteristics are due to the fact that an array is stored in a contiguous block of memory.  Computer memories are random-access ; that is, any item stored in memory can be retrieved by giving its address.  At the hardware level, addresses are integers from 0 up to the size of the memory.  Arrays are mapped into a contiguous block of addresses in the physical memory.  It is this random access property that makes array access by index a fast operation. 

On the other hand, it is the contiguous nature of the array that is responsible for its drawbacks.  An alternative is the linked list.  A linked list is comprised of a series of memory blocks called nodes.  Each node contains one data item along with a reference ("link") to the next node in the list, as shown below:



Some properties of linked lists:
  • Items need not be stored contiguously.  The logical order of the list may not be the same as its physical order.
  • To maintain a logical ordering, each item has a reference to the next item.
  • Items may be removed from the list by skipping over them in the link path.
  • Items may be added to the list by linking them in; that is, modifying a few of the links.
  • Sequential traversal (in logical order) can be performed by following the link path.
Linked lists are used frequently in the implementation of abstract data types.  Most data structure implementations are either array-based or link-based.

Several variations on the basic linked list are possible, such as
  • Maintaining both a head and tail pointer.
  • Using a sentinel node (dummy node) at the head or tail of the list.
  • Circular linked list.
  • Doubly-linked list.
To illustrate, let's see how we could use a linked list to implement the List interface:


/*
    Linked List implementation.  This implementation uses a local ListNode class.
    Each ListNode contains one data item and a link to the next node in the
    list.  The LinkedList class itself contains references to the head node and
    the tail node in the list.  It also keeps a count of the number of items in
    the list.
*/

public class LinkedList implements SimpleList
{
    int nitems;

    ListNode head,tail;

    public class ListNode {
        Object datum;
        ListNode next;

        ListNode(Object datum){
            this.datum = datum;
            next = null;
        }

        ListNode(Object datum, ListNode next){
            this.datum = datum;
            this.next = next;
        }

        public Object getDatum(){
            return datum;
        }

        public ListNode getNext(){
            return next;
        }
    }


LinkedList()
{
    nitems = 0;
    head = null;
    tail = null;
}

private ListNode getnth(int index)
{
    ListNode target = head;

    if(index<0 || index>=nitems)
        throw new IndexOutOfBoundsException();
    for(int k=0; k<index; k++)
        target = target.next;
    return target;
}

public void clear()
{
    nitems=0;
    head=tail=null;
}

public int size()
{
    return nitems;
}

public boolean isEmpty()
{
    return head==null;
}


public void prepend(Object item)
{
    if(isEmpty())
        head = tail = new ListNode(item);
    else
        head = new ListNode(item,head);
    ++nitems;
}

public boolean add(Object item)
{
    if(isEmpty())
        head = tail = new ListNode(item);
    else {
        tail = tail.next = new ListNode(item);
    }
    nitems++;
    return true;
}

public Object get(int index)
{
    return getnth(index).datum;
}

public Object set(int index, Object obj)
{
    ListNode node = getnth(index);
    Object temp = node.datum;
    node.datum = obj;
    return temp;
}

public Object remove(int index)
{
    Object target;

    if(index<0 || index>=nitems)
        throw new IndexOutOfBoundsException();
    else if(index==0){
        target = head.datum;
        head = head.next;
        if(nitems==1)
            tail = null;
        }
    else {
        ListNode prior = getnth(index-1);
        target = prior.next.datum;
        prior.next = prior.next.next;
        if(nitems==index+1)
            tail = prior;
        }
    --nitems;
    return target;
}

public void add(int index, Object item)
{
    if(index<0 || index>nitems)
        throw new IndexOutOfBoundsException();
    else if(index==nitems)
        add(item);
    else if(index==0)
        prepend(item);
    else {
        ListNode prior = getnth(index-1);
        prior.next = new ListNode(item,prior.next);
                ++nitems;
        }
}


}



Some advantages of linked lists:
  1. Access by pointer is faster than array indexing.
  2. Add and remove don't require shuffling data.
  3. They use only needed storage.
  4. Efficient operations:  adding or removing the first element; appending one list to another.
Some disadvantages:
  1. Process in forward order only (unless doubly-linked).
  2. Extra storage required for links.
  3. Inefficient operations:  access to the nth element.

 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: