Module 2, "Arrays,: Data Structures and Algorithms in Java 1 Module 5: Linked List
Module 2, "Arrays,: Data Structures and Algorithms in Java 1 Module 5: Linked List
This kind of class definition is sometimes called self-referential because it contains a field—called next in this case—of the
same type as itself.
We show only two data items in the link: an int and a double. In a typical application there would be many more. A
personnel record, for example, might have name, address, Social Security number, title, salary, and many other fields.
Often an object of a class that contains this data is used instead of the items:
class Link
{
public inventoryItem iI; // object holding data
public Link next; // reference to next link
}
all references, no matter what they refer to, are the same size. Thus it's no problem for the compiler to figure out how big
this field should be, and thereby construct an entire Link object.
Note that in Java, primitive types like int and double are stored quite differently than objects. Fields containing primitive
types do not contain references, but actual numerical values like 7 or 3.14159. A variable definition like
double salary = 65000.00;
creates a space in memory and puts the number 65000.00 into this space. However, a reference to an object, like
Link aLink = someLink;
puts a reference to an object of type Link, called someLink, into aLink. The someLink object isn't moved, or even created,
by this statement; it must have been created before. To create an object you must always use new:
Link someLink = new Link();
Even the someLink field doesn't hold an object, it's still just a reference. The object is somewhere else in memory, as shown
in Figure 5.2.
Other languages, like C++, handle objects quite differently than Java. In C++ a field like
Link next;
actually contains an object of type Link. You can't write a self-referential class definition in C++ (although you can put a
pointer to a Link in class Link; a pointer is similar to a reference). C++ programmers should keep in mind how Java
handles objects; it may be counter intuitive.
Before we get to the complete linkList.java program, we'll look at some important parts of the Link and LinkList
classes.
The Link Class
You've already seen the data part of the Link class. Here's the complete class definition:
class Link
{
public int iData; // data item
public double dData; // data item
public Link next; // next link in list
// ------------------------------------------------------------
// ------------------------------------------------------------
In addition to the data, there's a constructor and a method, displayLink(), that displays the link's data in the format {22,
33.9}. Object purists would probably object to naming this method displayLink(), arguing that it should be simply
display(). This would be in the spirit of polymorphism, but it makes the listing somewhat harder to understand when you
see a statement like
current.display();
and you've forgotten whether current is a Link object, a LinkList object, or something else.
The constructor initializes the data. There's no need to initialize the next field, because it's automatically set to null when
it's created. (Although it could be set to null explicitly, for clarity.) The null value means it doesn't refer to anything,
which is the situation until the link is connected to other links.
The LinkList Class
The LinkList class contains only one data item: a reference to the first link on the list. This reference is called first. It's the
only permanent information the list maintains about the location of any of the links. It finds the other links by following the
chain of references from first, using each link's next field.
class LinkList
{
private Link first; // ref to first link on list
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
The constructor for LinkList sets first to null. This isn't really necessary because as we noted, references are set to null
automatically when they're created. However, the explicit constructor makes it clear that this is how first begins.
When first has the value null, we know there are no items on the list. If there were any items, first would contain a
reference to the first one. The isEmpty() method uses this fact to determine whether the list is empty.
The insertFirst() Method
The insertFirst() method of LinkList inserts a new link at the beginning of the list. This is the easiest place to insert a
link, because first already points to the first link. To insert the new link, we need only set the next field in the newly
created link to point to the old first link, and then change first so it points to the newly created link. This is shown in
Figure 5.5.
In insertFirst() we begin by creating the new link using the data passed as arguments. Then we change the link
references as we just noted.
// insert at start of list
public void insertFirst(int id, double dd)
{ // make new link
Link newLink = new Link(id, dd);
newLink.next = first; // newLink --> old first
first = newLink; // first --> newLink
}
The arrows --> in the comments in the last two statements mean that a link (or the first field) connects to the next
(downstream) link. (In doubly linked lists we'll see upstream connections as well, symbolized by <-- arrows.) Compare
these two statements with Figure 5.5. Make sure you understand how the statements cause the links to be changed, as
shown in the figure. This kind of reference-manipulation is the heart of linked list algorithms.
The deleteFirst() Method
The deleteFirst() method is the reverse of insertFirst(). It disconnects the first link by rerouting first to point to the
second link. This second link is found by looking at the next field in the first link.
public Link deleteFirst() // delete first item
{ // (assumes list not empty)
Link temp = first; // save reference to link
first = first.next; // delete it: first-->old next
return temp; // return deleted link
}
Notice that the deleteFirst() method assumes the list is not empty. Before calling it, your program should verify this with
the isEmpty() method.
The displayList() Method
To display the list, you start at first and follow the chain of references from link to link.
A variable current points to (or technically refers to) each link in turn. It starts off pointing to first, which holds a
reference to the first link. The statement
current = current.next;
changes current to point to the next link, because that's what's in the next field in each link. Here's the entire
displayList() method:
public void displayList()
{
System.out.print("List (first-->last): ");
System.out.println("");
}
The end of the list is indicated by the next field in the last link pointing to null rather than another link. How did this field
get to be null? It started that way when the link was created and was never given any other value because it was always at
the end of the list. The while loop uses this condition to terminate itself when it reaches the end of the list.
Figure 5.7 shows how current steps along the list.
At each link, the displayList() method calls the displayLink() method to display the data in the link.
The linkList.java Program
Listing 5.1 shows the complete linkList.java program. You've already seen all the components except the main()
routine.
////////////////////////////////////////////////////////////////
class Link
{
public int iData; // data item (key)
public double dData; // data item
public Link next; // next link in list
// ------------------------------------------------------------
} // set to null)
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
System.out.println("");
}
// ------------------------------------------------------------
} // end main()
In main() we create a new list, insert four new links into it with insertFirst(), and display it. Then, in the while loop,
we remove the items one by one with deleteFirst() until the list is empty. The empty list is then displayed. Here's the
output from linkList.java:
List (first-->last): {88, 8.99} {66, 6.99} {44, 4.99} {22,2.99}
Deleted {88, 8.99}
Deleted {66, 6.99}
Deleted {44, 4.99}
Deleted {22, 2.99}
List (first-->last):
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------------------------------------------------------
while(current.iData != key)
{
if(current.next == null)
return null; // didn't find it
else
{
previous = current; // go to next link
current = current.next;
}
} // found it
if(current == first) // if first link,
first = first.next; // change first
else // otherwise,
previous.next = current.next; // bypass it
return current;
}
// ------------------------------------------------------------
System.out.println("");
}
// ------------------------------------------------------------
if( f != null)
System.out.println("Found link with key " + f.iData);
else
System.out.println("Can't find link");
if( d != null )
System.out.println("Deleted link with key " + d.iData);
else
System.out.println("Can't delete link");
theList.displayList(); // display list
} // end main()
} // end class LinkList2App
The main() routine makes a list, inserts four items, and displays the resulting list. It then searches for the item with key 44,
deletes the item with key 66, and displays the list again. Here's the output:
List (first-->last): {88, 8.99} {66, 6.99} {44, 4.99} {22,2.99}
Found link with key 44
Deleted link with key 66
List (first-->last): {88, 8.99} {44, 4.99} {22, 2.99}
// found it
if(current == first) // if first link,
first = first.next; // change first
else // otherwise,
previous.next = current.next; // bypass link
Other Methods
We've seen methods to insert and delete items at the start of a list and to find a specified item and delete a specified item.
You can imagine other useful list methods. For example, an insertAfter() method could find a link with a specified key
value and insert a new link following it. We'll see such a method when we talk about list iterators at the end of this module.