private Node mergeLists (Node first,
Node second)
{
Node head,
tail;
if (second
== null) // The second list is empty; return the first list.
head = first;
else if (first
== null) // The first list is empty; return the second list.
head = second;
else // Neither
list is empty, so set the head and tail to the smaller list head.
{
if (first.getId ().compareTo (second.getId ()) < 0)
{
head = first;
tail = first;
first = first.getNext ();
} // if
else
{
head = second;
tail = second;
second = second.getNext ();
} // else
while ((first != null) && (second != null)) // Merge the two lists
until one becomes empty.
{
if (first.getId ().compareTo (second.getId ()) < 0)
{
tail.setNext (first);
tail = first;
first = first.getNext ();
} // if
else
{
tail.setNext (second);
tail = second;
second = second.getNext ();
} // else
} // while
if (first == null) // If the first list is finished, attach the rest of
the second list.
tail.setNext (second);
else // Attach the remainder of the first list.
tail.setNext (first);
} // else
return head; // head points to the beginning of the combined lists.
} // method
merge
/* The method, doubleTime, sends the second pointer through the list twice as fast as the first. When the second one is null, it moves it to the node immediately following the first node and then sets the next field of the first node to null. This breaks the list into two lists. These are either the same size if the original list had an even number of nodes. Otherwise the first list has one more node than the second. */
private Node doubleTime (Node head)
{
Node first
= head, second;
if ((first
!= null) && (first.getNext () != null)) // The list has at least
two nodes.
{
second = first.getNext (); // This puts second one node ahead of first
to begin with.
while (second != null)
{
second = second.getNext (); // This puts second either at the next node
or makes it null.
if (second != null)
{
first = first.getNext (); // If second did not become null, first is advanced.
second = second.getNext (); // Second is kept two ahead of first with this.
}
}
second = first.getNext ();
first.setNext (null);
return second;
}
else // Either
the original list was empty or had just one node.
return null;
} // method doubleTime
/* The mergeSort method uses recursion to successively divide the lists into halves. When the lists consist of single nodes, they are then merged two at a time to create the final sorted list. */
public Node mergeSort (Node head)
{
if ((head
!= null) && (head.getNext () != null)) // The list contains at
least two nodes.
{
Node first = head;
Node second = doubleTime (head); // Find the middle of the list and break
the list into two.
first = mergeSort (first);
second = mergeSort (second);
head = mergeLists (first, second);
}
return head;
} // method mergeSort
} // class SortClass