SOURCE FILE: heapsort.pas


(*********************************************************)

PROCEDURE Swap
  (VAR Element1, Element2 : ListElementType);

  (* Swap the values of Element1 and Element2. *)

VAR
  Temp : ListElementType;

BEGIN (* Swap *)
  Temp := Element1;
  Element1 := Element2;
  Element2 := Temp
END;   (* Swap *)
(*********************************************************)

PROCEDURE ReheapDown
  (VAR Heap     : HeapType;
   Root, Bottom : Integer);
  (* Pre:  Root and Bottom are between 1 and Heap.NumElements. *)
  (*       Heap property violated only at Heap.Elements[Root], *)
  (*       if at all.                                          *)
  (* Post: Heap.Elements[Root]..Heap.Elements[Bottom] is a heap.*)
VAR
  MaxChild   : Integer; (* index of child with larger value *)
  RightChild : Integer; (* index of the right child node    *)
  LeftChild  : Integer; (* index of the left child node     *)

BEGIN (* ReheapDown *)
  WITH Heap DO
    BEGIN

      LeftChild  := Root * 2;
      RightChild := Root * 2 + 1;
      (* Check for Base Case 1: Heap.Elements[Root] is a leaf *)
      IF LeftChild <= Bottom
        THEN
          BEGIN  (* Heap.Elements[Root] is not a leaf *)
            (* MaxChild : index of child with larger value *)
            IF LeftChild = Bottom
              THEN (* There is only one child node. *)
                MaxChild := LeftChild
            ELSE (* Pick the greater of the two children. *)
               CASE HeapCompare(Elements[LeftChild],
                                Elements[RightChild]) OF
                 Greater  : MaxChild := LeftChild;
                 Less,
                 Equal    : MaxChild := RightChild
               END;  (* CASE *)
            (* Check for Base Case 2: order property intact *)
            CASE HeapCompare(Elements[Root], Elements[MaxChild]) OF
               Less   : (* General Case: swap and reheap *)
                         BEGIN
                           Swap (Elements[Root],
                                 Elements[MaxChild]);

                           ReheapDown (Heap, MaxChild, Bottom)
                         END;
                Equal,
                Greater : (* Order property is restored *);
              END;  (* CASE *)
      END (* IF Heap.Elements[Root] is not a leaf *)
   END (* WITH *)
END;   (* ReheapDown *)

(*********************************************************)

PROCEDURE ReheapUp
  (VAR Heap     : HeapType;
   Root, Bottom : Integer);
  (* Pre:  Root and Bottom are between 1 and Heap.NumElements.   *)
  (*       Order property violated only at Heap.Elements[Bottom] *)
  (*       if at all.                                            *)
  (* Post: Heap.Elements[Root]..Heap.Elements[Bottom] is a heap. *)
VAR
  Parent : Integer; (* index of the parent node *)

BEGIN (* ReheapUp *)
  WITH Heap DO
    (* Check for Base Case 1: Heap.Elements[Bottom] is the root *)
    IF Bottom > Root
      THEN
        BEGIN  (* Heap.Elements[Bottom] is not the root *)
          Parent := Bottom DIV 2;
          (* Check for Base Case 2: order property intact *)
          CASE HeapCompare(Elements[Parent], Elements[Bottom]) OF
            Less    : BEGIN (* General case: swap and reheap *)
                        Swap (Elements[Parent], Elements[Bottom]);
                        ReheapUp (Heap, Root, Parent)
                      END;
            Equal,
            Greater : (* Base case 2: Heap property is restored *);
          END;  (* CASE *)
        END (* IF Heap.Elements[Bottom] is not root *)
END;  (* ReheapUp *)

(*************************************************************)

PROCEDURE HeapSort
  (VAR List : ListType);

  (* Sort the elements in List in ascending order, using *)
  (* the HeapSort algorithm.                             *)

VAR
  Index : IndexType;

BEGIN (* HeapSort *)

  WITH List DO
    BEGIN

      (* Build the original heap from the unsorted elements. *)
      FOR Index := (Length DIV 2) DOWNTO 1 DO
        ReheapDo             *)
      FOR Index := Length DOWNTO 2 DO
        BEGIN
          Swap (Info[1], Info[Index]);
          ReheapDown (Info, 1, Index - 1)
        END  (* FOR loop *)
    END (* WITH *)
END;   (* HeapSort *)