CS 415, Section 002 Sonoma State University Spring, 2022
 
Algorithm Analysis
Instructor: Henry M. Walker

Lecturer, Sonoma State University
Professor Emeritus of Computer Science and Mathematics, Grinnell College

Lab:  Heaps

Summary

This lab provides practice with several basic algorithms related to heaps, as implemented with arrays.

Discussion

A max-heap is a binary tree with the property that the value at each node is larger (according to some ordering) than the values stored in either child. Similarly, a min-heap is a binary tree with the property that the value at each node is smaller (according to some ordering) than the values stored in either child.

Further, we restrict our attention to trees which are completely balanced. All nodes have 2 children, except at the bottom of the tree. The last row of the tree may not be full, but any items on the last level are moved left as much as possible. For example, the following tree illustrates the shape of a tree and the ordering of values within the tree for a max-heap.

typical heap

A Simple Labeling of Nodes

To identify the nodes in a tree, the simplest approach is to number the nodes level-by-level from the root downward. Within a level, nodes are numbered left to right. Also, for simplicity, many textbooks assign the index 1 to the root node.

standard labeling

In examining the label nodes, a pattern emerges: for each node labeled i, the left child has label 2*i and the right node has label 2*i+1.

detail for standard labeling

Note: As previously noted, some textbooks, such as Data Structures and Problem Solving Using Java, Fourth Edition by Mark Allen Weiss. uses this numbering scheme in writing code, with the top node numbered 1. If one considers an array element 0, Weiss suggests filling that position with -∞ for a min-heap or ∞ for a max-heap.

0-based Labeling of Nodes

If we start labeling at 0 rather than 1, the labeling of nodes becomes:

0-based labeling
  1. In the context of 0-based labeling, identify a pattern for moving from a node with label j to its left child and its right child. What labels would be found on the left and right nodes of a node with label j?

detail for 0-based labeling

Connecting a Heap with an Array

Since nodes in a heap fit a straight forward identification system, there is a natural mapping between the logical nodes in a heap and the indexed elements of an array.

Insertion into a Heap

In class we considered how to insert an item into a heap and maintain the structure. In each case, we first place the item at the end of a tree (as far left as possible in the last row). The item then is worked up from its position, until the data in the tree are appropriately ordered.

  1. The following heap repeats the structure given at the beginning of this lab:

    typical heap

    Using this structure as a start, insert the values 30, 25, 55, 81, and 95. Show the structure of the tree and the values in each node after each insertion.

Deletion from a Heap

In class, we also considered how to remove the top-priority item from a heap: remove the root as the item to be returned, move the last item from the end of the heap to the root, and work that item down in the heap until the data are properly ordered.

  1. Starting with the original heap from step 2, remove four items in sequence. Show the structure of the tree and the values in each node after each deletion.

Constructing a Heap within an Array

In class, we discussed starting with an array of data and working from the bottom toward the top to rearrange the data to yield a heap. For Steps 4 and 5, consider working with a min-heap.

In the following steps, consider a heap implemented with 0-based indexing.

  1. Suppose an array of twelve elements, a[12], is initialized with a[i] = 20-i for each i. What rearrangements, if any, need to be done in order to make the corresponding tree structure into a heap? Show the data in the array once a heap is achieved.

  2. Suppose the array of twelve elements, a[12], is initialized with a[i] = i for each i. What rearrangements, if any, need to be done in order to make the corresponding tree structure into a heap? Show the data in the array once a heap is achieved.

The percolateDown Method

The following parts of this lab are lightly edited from a "Heap Sort" lab, written by Jerod Weinmen.

Steps 6—9 of this lab refer to a partially-written HeapSort.cpp program.

  1. Copy this program to your workstation for use in the rest of this lab.

The following Java code is taken from Figure 21.14 in Data Structures and Problem Solving Using Java, Fourth Edition by Mark Allen Weiss.

     /**
      * Internal method to percolate down in the heap.
      *
      * @param hole the index at which the percolate begins.
      */
    private void percolateDown( int hole )
    {
        int child;
        AnyType tmp = array[ hole ];

        for( ; hole * 2 <= currentSize; hole = child )
        {
            child = hole * 2;
            if( child != currentSize &&
                    compare( array[ child + 1 ], array[ child ] ) < 0 )
                child++;
            if( compare( array[ child ], tmp ) < 0 )
                array[ hole ] = array[ child ];
            else
                break;
        }
        array[ hole ] = tmp;
    }

In this code, Weiss uses a special value -∞ as a special value at array location zero, and actual coding uses array elements 1 through currentsize. This impacts where the children are, as well as how the size of the heap relates to the index of the last node.

In the next exercises, you will translate this code to C++ and modify the logic to use a zero-based heap, rather than the one-based heap this method is written for.

  1. Record your answers to the following questions on paper, so as to help you develop your solution.

    1. What is the effect and purpose of the statements assigning tmp to array[ hole ] and vice-versa?
    2. What is the meaning of the following for-loop test? That is, what is it expressing?
      hole * 2 <= currentSize
    3. What is the meaning and purpose of the for-loop "increment" hole = child?
    4. What does the assignment to child accomplish? What child is this? (No singing Greensleeves, now.) Left or right?
    5. What does it mean if child == currentSize?
    6. How would you express this same meaning in a zero-based heap?
    7. What is the effect of the child++? (That is, what is the meaning, not "the integer child is increased by one").
    8. Why does the compare statement indicate the increment is reasonable and appropriate?
    9. What does the following assignment do?
      array[ hole ] = array[ child ];
      Why shouldn't we be worried about overwriting the array entry at hole?
    10. Why does the compare statement indicate this is the appropriate action?
    11. Why do we break out of the loop otherwise?
  2. Complete the HeapSort program:

    1. HeapSort.cpp contains several methods—most notably, heapSort, the implementation of a standard heapsort given in Weiss' textbook. Review that now and be sure you understand how it works.
    2. Inspect the signature and documentation of the percDown method to be sure you understand how it is supposed to work.
    3. Using your answers from exercise 2, and the original implementation of percolateDown as a model, implement this version of percolate down, taking note of the following two important differences:
      • This version uses a max heap, and
      • there is no sentinel at zero, so the first datum appears at array[0].
  3. Run your revised program, and review the test cases for correctness.

    If the answers are not correct, I suggest you use a smaller heap (i.e., 2(3+1)-1=7 nodes), and add print statements that tell you where the hole is, what is being swapped for what, and what indices the swap is between. In addition, you may wish to carefully review your answers to the questions in Exercise 1, and make sure the logic (in addition to the arithmetic) still holds for your implementation in Exercise 2.

created 7 May 2012 by Henry M. Walker
revised 7 May 2012 by Henry M. Walker
expanded with code 11 January 2013 by Henry M. Walker
steps 4 and 5 clarified 13 December 2014 by Henry M. Walker
minor editing 30 November 2018 by Henry M. Walker
revised December-January 2021
rewritten with C++ for CS 415 at SSU December 30, 2021 by Henry M. Walker
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.