Computer Science at SUNY Brockport


Heap Sort Animation with User Input


Algorithm Description

adjust(int Root)
{
	node = Root;
 	if (isleaf(node)) return;
	else
	if ((node.value >= node.leftchild.value) && (node.value >= 
		node.rightchild.value))
		return;
	else
	if (there exists a child with a larger value)
	   {	largerChild = child with larger of the two child values;
		swap (largerChild.value, node.value);
	adjust(largerChild);
}

constructInitHeap()
{
  	for (RootNode = n/2; RootNode >= 0; RootNode--)
                    adjust(node(RootNode));
}

HeapSort() 
{
 	for (RootNode = n; RootNode >= 0; RootNode--)
                {
                    swap(List[1], List[RootNode]);
                    adjust(node(0));
}

Note : This algorithm sorts in ascending order - i.e., smaller elements move to the front of the list.


Instructions on use of the applet

The user of the applet is advised to read this section in order to make the best use of the applet. If you have a large enough browser window, this page should be scrolled so that the applet itself (including the interaction panel at the bottom of the display part of the applet) is visible along with these instructions. The buttons in the interaction panel are to be used in the following manner:

Applet


NOTE : Clicking on the ">>" or "<<" buttons will move the sort forward (or backward) at a VERY FAST pace, which may be unobservable. These are essentially "Fast Forward" or "Rewind" buttons. If you want to see the sort move ahead at a reasonable pace, click on the "Slow" button and then use the slider bar to adjust the delay to a suitable value.


Heap Sort Animation with User Input


Explanation of operation

Heap Sort operates by first converting the initial array into a heap. Heap is defined as a binary tree in which each node has a value greater than BOTH its children (if any). Each node in the heap corresponds to a particular element of the array, with the root node corresponding to the element with index 0. If we consider the index associated with a particular node to be i, then the left child of this node corresponds to the element with index 2*i+1 and the right child corresponds to the element with index 2*i+2. If any or both of these elements do not exist in the array, then the corresponding child node does not exist either. Observe, therefore, than in the heap, the largest element will always be located at the root.

The HeapSort algorithm uses a process called "adjust" to accomplish its job. The adjust algorithm, as shown above, receives a binary tree that is ALMOST a heap as input and converts it to a heap. By almost a heap we mean that both the left and right subtrees are heaps, but the whole tree is not a heap (in other words, the root of the heap is the only culprit). This root is then compared with its two immediate children, and the larger child is swapped with it. This may result in one of the left- or right subtrees losing their heap property. Consequently, the "adjust" algorithm is recursively applied to the appropriate subtree (rooted at the newly "offending" child - i.e., the one whose value was just swapped with the root) and the process continues until either a leaf node is reached, or it is determined that the heap property is satisfied in the subtree.

The entire HeapSort method consists of two major steps:

  1. Construct the initial heap using adjust (n/2) times on all non-leaf nodes (Phase 1).
  2. Sort by swapping and adjusting the heap (n-1) times (Phase 2).

    Let us examine in some more detail what happens in Phase 2. Since the largest element of the heap is always at the root, after the initial heap is constructed, the root value is swapped with the lowest, rightmost element (i.e., the node with value 8 - note the situation at the end of iteration 17 in the above applet when the first heap is completely constructed). This lowest, rightmost node corresponds to the last element of the array (right?) and so after the swapping the righmost element of the array has the largest value, which is what we want it to have. Consequently, the rightmost element is correctly place, and so the corresponding node becomes a light gray in the tree display depicting the heap. Also, the elements (nodes) chosen for swapping at this point of the algorithm are shown as yellow nodes.

    Thereafter, since the value of the lowest, rightmost node has moved up to the root, the heap property of the rest of the heap (minus the light gray nodes) has been disturbed. Consequently, now the "adjust" process is applied to the rest of the heap (treating the light gray nodes as though they were no longer a part of the heap). Once the rest of the heap is again converted to a proper heap, the swapping process as described in the previous paragraph, followed by the adjust process is applied again. This continues until the root node of the heap turns light gray - i.e., the root has its correct value. Then, the array is sorted.


Complexity of the algorithm

At each step of the "adjust" algorithm, a node is compared to its children and one of them is chosen as the next root. We drop one level of the tree at each step of this process. Since this is a complete binary tree, there are at most log(n) levels. Thus, the worst case time complexity of "adjust" is O(log(n)). In the Heapsort algorithm, we simply use "adjust" (n/2 times in Phase 1 and (n-1) times in Phase 2. Thus, HeapSort has a worst-case time complexity of O(n*log(n)).