/* * --- GSMP-COPYRIGHT-NOTE-BEGIN --- * * This copyright note is auto-generated by ./scripts/Create-CopyPatch. * Please add additional copyright information _after_ the line containing * the GSMP-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by * the ./scripts/Create-CopyPatch script. Do not edit this copyright text! * * GSMP: utility/include/template/BinomiHeap.tcc * General Sound Manipulation Program is Copyright (C) 2000 - 2004 * Valentin Ziegler and René Rebe * * 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; version 2. A copy of the GNU General * Public License can be found in the file LICENSE. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT- * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * --- GSMP-COPYRIGHT-NOTE-END --- */ #ifndef BIN_HEAP_HH__ # error "This file is included by BinomiHeap.hh" # error "manual inclusion is nonsense" #endif // BIN_HEAP_HH__ template BinomiHeap :: BinomiHeap () { heap.push_back (0); // insert pseudo element cur_size = 1; } template BinomiHeap :: ~BinomiHeap () { } template id_t BinomiHeap :: Insert (ITEM_T item, KEY_T key) { // init node data id_t id = node_data.size(); node_data.push_back (Node (item, key, cur_size)); // insert at end of heap unsigned int node_pos = id; if (cur_size > MaxElements()) heap.push_back (node_pos); else heap[cur_size] = node_pos; unsigned int pos = cur_size; cur_size++; DrownElement (pos, key); return id; } template ITEM_T BinomiHeap :: ExtractMin (KEY_T& val) { if (RANGE_CHECKING) if (Empty()) throw HeapEmptyException(); // remember root data Node& t_node = node_data[heap [1]]; ITEM_T r_item = t_node.item; val = t_node.key; // mark root as extracted t_node.map_position = 0; if (CurrentElements() > 1) { // insert last element as new root heap [1] = heap [--cur_size]; Node& new_root = node_data[heap [1]]; new_root.map_position = 1; // bubble element upwards unsigned int pos = 1; KEY_T key = new_root.key; unsigned int spos; while (spos = SmallestChildIndex (pos), node_data[heap [spos]].key < key) { ExchangeNodes (pos, spos); pos = spos; } } else cur_size--; return r_item; } template inline unsigned int BinomiHeap :: TotalIDs () { return node_data.size(); } template inline unsigned int BinomiHeap :: CurrentElements () { return cur_size - 1; } template inline unsigned int BinomiHeap :: MaxElements () { return heap.size() - 1; } template inline bool BinomiHeap :: Empty () { return CurrentElements() == 0; } template void BinomiHeap :: DecreaseKey (KEY_T new_key, id_t id) { CheckInQ (id); if (RANGE_CHECKING) if (node_data [id].key < new_key) throw InvalidKeyException(); node_data [id].key = new_key; unsigned int pos = (unsigned int) node_data[id].map_position; DrownElement (pos, new_key); } template KEY_T BinomiHeap :: GetKey (id_t id) { CheckId (id); return node_data[id].key; } template ITEM_T BinomiHeap :: GetItem (id_t id) { CheckId (id); return node_data [id].item; } template inline bool BinomiHeap :: InHeap (id_t id) { CheckId(id); return (node_data[id].map_position > 0); } template void BinomiHeap :: DrownElement (unsigned int pos, KEY_T key) { // drown element unsigned int mother; while (pos > 1 && (mother = MotherIndex(pos), node_data[heap [mother]].key > key)) { ExchangeNodes (pos, mother); pos = mother; } } template inline void BinomiHeap :: ExchangeNodes (int i, int j) { unsigned int dummy = heap [i]; heap [i] = heap [j]; heap [j] = dummy; node_data[heap [i]].map_position = i; node_data[heap [j]].map_position = j; } template inline unsigned int BinomiHeap :: LeftChildIndex (int index) { // child 1 on position [index * 2] return index << 1; } template inline unsigned int BinomiHeap :: RightChildIndex (int index) { // child 2 on position [index * 2] + 1 return (index << 1) + 1; } template inline unsigned int BinomiHeap :: SmallestChildIndex (int index) { unsigned int l = LeftChildIndex (index); unsigned int r = RightChildIndex (index); unsigned int elements=CurrentElements(); if (l > elements) return index; // node does not have any children else if (l == elements) return l; // node only features one children else return (node_data[heap [l]].key < node_data[heap [r]].key) ? l : r; } template inline unsigned int BinomiHeap :: MotherIndex (int index) { // mother at position [index / 2] return index >> 1; } template inline void BinomiHeap :: CheckId (id_t id) { if (RANGE_CHECKING) if (id >= TotalIDs()) throw InvalidIdException(); } template inline void BinomiHeap :: CheckInQ (id_t id) { if (!InHeap(id)) throw InvalidIdException(); } #ifdef HEAP_TESTING template void BinomiHeap :: PrintHeap (unsigned int pos, unsigned int spaces) { for (unsigned int i=0; i elements) ; // node does not have any children else if (l == elements) { // node only features one children PrintHeap (l, spaces+1); } else { PrintHeap (l, spaces+1); PrintHeap (r, spaces+1); } } #endif