#
#  File: heap.k3
#  Handles a heap
#
#  Copyright 2005 Radboud University of Nijmegen
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Library General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#  CVS ID: "$Id: heap.k3,v 1.7 2005/10/19 11:53:04 marcs Exp $"
#
MODULE heap = HEAP{} HEAP_SIZE MAX_HEAP_SIZE HEAP_BASE.

DEFINES
    ITEM,
    ACTION reset heap,
    ACTION clear heap,
    ACTION add to heap (>ITEM),
    FUNCTION get from heap (>INT, TEXT>),
    FUNCTION get from heap (>INT, INT1>, INT2>),
    FUNCTION get heap size (INT>),
    ACTION sort heap segment (>INT1, >INT2),
    ACTION sort heap.

#################
#               #
#   Heap sort   #
#               #
#################

HEAP          = ITEM.
HEAP_BASE     = INT.
HEAP_SIZE     = INT.
MAX_HEAP_SIZE = INT.

ITEM :: TEXT;
        key INT item INT;
        destroyed.

PRELUDE init heap:
   actual init heap.

ACTION actual init heap:
  [0 -> HEAP_BASE],
    [0 -> HEAP_SIZE],
    [0 -> MAX_HEAP_SIZE].

ACTION reset heap:
  [0 -> HEAP_BASE],
    maximize MAX_HEAP_SIZE with HEAP_SIZE,
    [0 -> HEAP_SIZE].

FUNCTION maximize >INT1> with >INT2:
  less (INT1, INT2),
    [INT2 -> INT1];
  +.
  
ACTION clear heap:
  clear heap (MAX_HEAP_SIZE),
    actual init heap.

ACTION clear heap (>INT):
  [INT -> 0];
  [INT - 1 -> INT],
    [destroyed -> HEAP{INT}],
    clear heap (INT).

ACTION add to heap (>ITEM):
  [ITEM -> HEAP{HEAP_SIZE}],
    [HEAP_SIZE + 1 -> HEAP_SIZE].

FUNCTION get from heap (>INT, TEXT>):
  [HEAP{INT} -> TEXT];
  ?.

FUNCTION get from heap (>INT, INT1>, INT2>):
  [HEAP{INT} -> key INT1 item INT2];
  ?.

FUNCTION get heap size (INT>):
  [HEAP_SIZE -> INT].

ACTION swap (>INT1, >INT2):
  [HEAP{INT2} -> ITEM],
    [HEAP{INT1} -> HEAP{INT2}],
    [ITEM -> HEAP{INT1}].

TEST where >INT1 greater >INT2:
  before (HEAP{INT2}, HEAP{INT1}).

TEST before (>ITEM1, >ITEM2):
  [ITEM1 -> TEXT1],
    [ITEM2 -> TEXT2],
      (before (TEXT1, TEXT2);
       -);
  [ITEM1 -> key INT1 item INT],
    [ITEM2 -> key INT2 item INT],
      (less (INT1, INT2);
       -);
  ?.

TEST where >INT1 has son INT2> below >INT:
  where INT1 has son INT2,
    less (INT2, INT).

TEST where >INT1 has brother INT2> below >INT:
  where INT1 has brother INT2,
    less (INT2, INT).

FUNCTION where >INT1 has son INT2>:
  [2 * INT1 - HEAP_BASE + 1 -> INT2].

FUNCTION where >INT1 has brother INT2>:
  [INT1 + 1 -> INT2].

ACTION sort heap segment (>INT1, >INT2):
  [INT1 -> HEAP_BASE],
    sort heap (INT2).

ACTION sort heap: 
  [0 -> HEAP_BASE],
    get heap size (INT),
    sort heap (INT).

ACTION sort heap (>INT):
  create heap (INT, INT),
    order heap (INT).

ACTION create heap (>INT1, >INT2):
  lesseq (INT1, HEAP_BASE);
  [INT1 - 1 -> INT1],
    restore heap (INT1, INT2),
    create heap (INT1, INT2).

ACTION order heap (>INT):
  lesseq (INT, HEAP_BASE);
  [INT - 1 -> INT],
    swap (HEAP_BASE, INT),
    restore heap (HEAP_BASE, INT),
    order heap (INT).

ACTION restore heap (>INT1, >INT2):
  where INT1 has greater greatest son INT below INT2,
    swap (INT1, INT),
    restore heap (INT, INT2);
  +.

TEST where >INT1 has greater greatest son INT2> below >INT:
  where INT1 has son INT2 below INT,
    (where INT2 has greater brother INT3 below INT,
       where INT3 greater INT1,
       [INT3 -> INT2];
     where INT2 greater INT1).

TEST where >INT1 has greater brother INT2> below >INT:
  where INT1 has brother INT2 below INT,
    where INT2 greater INT1.

