Linked lists Comparing arrays with linked lists

Document Sample
Linked lists Comparing arrays with linked lists Powered By Docstoc
					COMP 250 Winter 2010 lectures 4,5 – linked lists [modified Jan. 21]                January 13 & 15, 2010


Linked lists
We next consider an alternative data structure for ordering a set of objects. Again, we have a set
of objects that constructed one-by-one. But now we do not know in advance how many objects
we will have (unlike in the case of an array, where we need to define the size of the array when
we construct it). We define a data structure that links these objects together such that they are
ordered (like with an array) and we can talk about the first object, the second one, etc. We will
have methods that give us access to the first object (i.e. we can add or remove the first object from
the “list”) and, if we have access to any object then we have methods to access the next object.
Note that these basic two requirements give us access to all the objects: we start at the first one
and then follow each one to the next.
    We start by defining a linked list node. Each node contains a reference to an object (alternatively,
it could contain a primitive variable e.g. a list of numbers or characters), along with a reference to
the next object in the list.
    In today’s lecture and the next one (4,5), I cover some of the basic manipulations that one does
with a list, namely adding and removing nodes. I will not reproduce the whole discussion here. You
should consult the PDFs of the slides to see the figures. I am also providing a Java implementation
of a single linked list and a doubly linked list, which you should carefully examine and test. (In
class, I did not discuss the Java implementation. But for Assignment 1, you will need to code up a
list using Java. And for Quiz 1 you may be given Java code that manipulates lists. So you would
be wise to have a close look at the code and spend a bit of time working with it.)

Comparing arrays with linked lists
At the end of lecture 5, I compared the number of operations needed to add or remove a node,
using arrays vs. singly linked lists vs. doubly linked lists.
    To keep the discussion as simple as possible, lets suppose that there are N objects in a particular
order. For the array, we require that the objects are in positions a[0], . . . , a[N − 1], i.e. no holes in
the array. We also require that the array is of size strictly greater than N so that when we want
to add an element, we don’t need to be concerned about whether there is a slot available. We only
deal with the case now in which there is a slot available.

addFirst, removeFirst
Suppose we wish to add an object, in particular, we wish to add it to the front of the ordering. We
can call the operation “addFirst” or “addHead”, for example. If we are using an array, then we
need to shift the references for each of the N objects that are currently in array, namely we need
to:

  for (i = N-1 downto 0)
     a[i+1] <-- a[i]

  a[0] <-- new element

Notice that we are not moving the objects themselves, i.e. we are not changing the references.
Rather we are just moving the references within the array. Notice that N operations are required


                                                    1
COMP 250 Winter 2010 lectures 4,5 – linked lists [modified Jan. 21]                   January 13 & 15, 2010


here. Similarly, to remove the first element, we shift the elements a[1], . . . , a[N −1] to a[0], . . . , a[N −
2] (using N − 1 steps) and set a[N − 1] to null. Again, N operations are done.
    Compare these N array operations to what is done if a linked list is used. In the latter case
case, one only needs a few operations, e.g. one needs to manipulate the “head” reference.

addLast, removeLast
If we wish to add a new last element or remove the current last element (i.e. “back” element, or
“tail” element) then the array works well since we don’t have to shift elements around. In the
case of adding, we are just putting a reference into a[N] and then incrementing N (the number of
elements present in the array). In the case of removing the last element, we are replace a[N − 1]
with a null reference and then decrement N.
    If we use a singly linked list, then we can add a new last node with just a few operations, namely
we need to manipulate the tail reference. Removing the last node is more expensive. Even though
we may have a reference variable tail that tells us where this last node is, we don’t know which
node precedes tail (as discussed during the lecture). The only way to find this preceeding node is
to use a while loop and step all the way from head to tail. This takes N operations.
    For a doubly linked list, we can add and remove the last element in the list in just a few
operations (assuming of course that we have a tail reference available).

add(i, node), remove(i)
What about if we are trying to add an element to the i-th position (in which case we need to make
room for it) or we want to remove the i-th element? By the term “adding” here, I mean “inserting”.
We are increasing the number of elements by 1 and placing this new element at a particular position.
     For the case of an array, adding to or removing an element from position i requires that we shift
N − i reference variables. If i ≈ N then only a small number of operations are required. However,
if i ≈ 0, then approximately N operations will be required.
     For a singly linked list with N elements, we need i steps, namely we need to start from the head
and count 0,1,2,.. until we reach element i. If i ≈ N then this will take approximately N steps. If
i ≈ 0, though, then we will find i-th element quickly and the add (or remove) can be done quickly.


Summary
So, are arrays better or worse that lists ? And are singly linked lists better or worse than doubly
linked lists? There is no unique answer to these questions. Rather the choice of data structure
depends what operations we are typically doing. If we are always adding and removing from the
front (head), then we don’t want to use arrays, and we don’t need to use doubly linked lists (which
require an extra reference variable, namely prev and extra instructions for setting this variable). If
we are only adding to the back of the ordering, then an array should be fine. If we are adding or
removing from an arbitrary position, then we might want to consider using a doubly linked list.




                                                      2