      1 var define = require("../define").define,
      2         Collection = require("./Collection"),
      3         base = require("../base");
      4
      5 var padding = function(char, numSpaces) {
      6     var ret = [];
      7     for (var i = 0; i < numSpaces; i++)
      8         ret.push(char);
      9     return ret.join("");
     10 };
     11
     12 module.exports = exports = define(Collection, {
     13     instance : {
     14         /**@lends comb.collections.Heap.prototype*/
     15         __getParentIndex : function(index) {
     16             return Math.floor((index - 1) / 2);
     17         },
     18
     19         __getLeftChildIndex : function(index) {
     20             return (index * 2) + 1;
     21         },
     22
     23         __getRightChildIndex : function(index) {
     24             return (index * 2) + 2;
     25         },
     26
     27         __makeNode : function(key, value) {
     28             return {key : key, value : value};
     29         },
     30
     31
     32         /**
     33          * Base class for Heap Implementations.
     34          *
     35          *
     36          * @constructs
     37          * @augments comb.collections.Collection
     38          * @memberOf comb.collections
     39          *
     40          * @property {Number} count the current number of elements.
     41          * @property {Array} keys the keys of all items in the heap.
     42          * @property {Array} values the values contained in the heap.
     43          * @property {Boolean} isEmpty true if the Heap is empty.
     44          */
     45         constructor : function() {
     46             this.__heap = [];
     47         },
     48
     49         /**
     50          * Insert a key value into the key
     51          * @param key
     52          * @param value
     53          */
     54         insert : function(key, value) {
     55             if (!base.isString(key)) {
     56                 var l = this.__heap.push(this.__makeNode(key, value));
     57                 this.__upHeap(l - 1);
     58             } else {
     59                 throw TypeError("Invalid key");
     60             }
     61         },
     62
     63         /**
     64          * Removes the root from the heap
     65          *
     66          * @returns the value of the root
     67          */
     68         remove : function() {
     69             var ret = undefined, heap = this.__heap, l = heap.length;
     70             if (l) {
     71                 ret = heap[0];
     72                 if (l == 1) {
     73                     heap.length = 0;
     74                 } else {
     75                     heap[0] = heap.pop();
     76                     this.__downHeap(0);
     77                 }
     78             }
     79             return ret ? ret.value : ret;
     80         },
     81
     82         /**
     83          * Gets he value of the root node with out removing it.
     84          *
     85          * @returns the value of the root
     86          */
     87         peek : function() {
     88             var ret = undefined, heap = this.__heap, l = heap.length;
     89             if (l) {
     90                 ret = heap[0];
     91             }
     92             return ret ? ret.value : ret;
     93         },
     94
     95         /**
     96          * Gets the key of the root node without removing it.
     97          *
     98          * @returns the key of the root
     99          */
    100         peekKey : function() {
    101             var ret = undefined, heap = this.__heap, l = heap.length;
    102             if (l) {
    103                 ret = heap[0];
    104             }
    105             return ret ? ret.key : ret;
    106         },
    107
    108         /**
    109          * Perform the heapify operation after the an
    110          * item as been added to the bottom of the heap.
    111          *
    112          * @param index the index in which the new item was added
    113          */
    114         __upHeap : function(index) {
    115             throw Error("NOT IMPLEMENTED");
    116         },
    117
    118         /**
    119          * Heapify the heap after the root has been removed
    120          *
    121          * @param index the index of the root
    122          */
    123         __downHeap : function(index) {
    124             throw Error("NOT IMPLEMENTED");
    125         },
    126
    127         /**
    128          *
    129          * Determine if the heap contains a particular key.
    130          *
    131          * @param key key to test.
    132          *
    133          * @returns {Boolean} true if the key is contained in this heap.
    134          */
    135         containsKey : function(key) {
    136             var heap = this.__heap;
    137             for (var i = heap.length - 1; i >= 0; i--) {
    138                 if (heap[i].key == key) {
    139                     return true;
    140                 }
    141             }
    142             return false;
    143         },
    144
    145         /**
    146          *
    147          * Determine if the heap contains a particular value.
    148          *
    149          * @param value value to test.
    150          *
    151          * @returns {Boolean} true if the value is contained in this heap.
    152          */
    153         containsValue : function(value) {
    154             var heap = this.__heap;
    155             for (var i = heap.length - 1; i >= 0; i--) {
    156                 if (heap[i].value == value) {
    157                     return true;
    158                 }
    159             }
    160             return false;
    161         },
    162
    163         /**
    164          * Empty the heap.
    165          */
    166         clear : function() {
    167             this.__heap.length = 0;
    168         },
    169
    170         __printNode : function(index, level) {
    171             //console.log(level);
    172             var str = [], node = this.__heap[index];
    173             if (node == null || node == undefined) {
    174                 str.push(padding('\t', level));
    175                 str.push("~");
    176                 console.log(str.join(""));
    177             } else {
    178                 this.__printNode(this.__getRightChildIndex(index), level + 1);
    179                 str.push(padding('\t', level));
    180                 str.push(node.key + " : " + node.value + "\n");
    181                 console.log(str.join(""));
    182                 this.__printNode(this.__getLeftChildIndex(index), level + 1);
    183             }
    184         },
    185
    186         /**
    187          * Print the heap.
    188          */
    189         print : function() {
    190             this.__printNode(0, 0);
    191         },
    192
    193         getters : {
    194
    195             count : function() {
    196                 return this.__heap.length;
    197             },
    198
    199             keys : function() {
    200                 return this.__heap.map(function(n) {
    201                     return n.key;
    202                 });
    203             },
    204
    205             values : function() {
    206                 return this.__heap.map(function(n) {
    207                     return n.value;
    208                 });
    209             },
    210
    211             isEmpty : function() {
    212                 return this.__heap.length == 0;
    213             }
    214         }
    215
    216
    217     }
    218 });