Files
gtk3/debian/missing-sources/zlib.js-0.1.6/src/heap.js
Simon McVittie 7e6de580a7 * debian/missing-sources/zlib.js-0.1.6: add missing source code for gdk/broadway/rawinflate.min.js (Closes: #753968)
- some files in zlib.js upstream had missing source code themselves
    (closure-compiler.jar) or are not needed here, and have been removed
    to save space; see debian/missing-sources/README for details
2014-08-11 09:43:29 +00:00

136 lines
3.1 KiB
JavaScript

/**
* @fileoverview Heap Sort 実装. ハフマン符号化で使用する.
*/
goog.provide('Zlib.Heap');
goog.require('USE_TYPEDARRAY');
goog.scope(function() {
/**
* カスタムハフマン符号で使用するヒープ実装
* @param {number} length ヒープサイズ.
* @constructor
*/
Zlib.Heap = function(length) {
this.buffer = new (USE_TYPEDARRAY ? Uint16Array : Array)(length * 2);
this.length = 0;
};
/**
* 親ノードの index 取得
* @param {number} index 子ノードの index.
* @return {number} 親ノードの index.
*
*/
Zlib.Heap.prototype.getParent = function(index) {
return ((index - 2) / 4 | 0) * 2;
};
/**
* 子ノードの index 取得
* @param {number} index 親ノードの index.
* @return {number} 子ノードの index.
*/
Zlib.Heap.prototype.getChild = function(index) {
return 2 * index + 2;
};
/**
* Heap に値を追加する
* @param {number} index キー index.
* @param {number} value 値.
* @return {number} 現在のヒープ長.
*/
Zlib.Heap.prototype.push = function(index, value) {
var current, parent,
heap = this.buffer,
swap;
current = this.length;
heap[this.length++] = value;
heap[this.length++] = index;
// ルートノードにたどり着くまで入れ替えを試みる
while (current > 0) {
parent = this.getParent(current);
// 親ノードと比較して親の方が小さければ入れ替える
if (heap[current] > heap[parent]) {
swap = heap[current];
heap[current] = heap[parent];
heap[parent] = swap;
swap = heap[current + 1];
heap[current + 1] = heap[parent + 1];
heap[parent + 1] = swap;
current = parent;
// 入れ替えが必要なくなったらそこで抜ける
} else {
break;
}
}
return this.length;
};
/**
* Heapから一番大きい値を返す
* @return {{index: number, value: number, length: number}} {index: キーindex,
* value: 値, length: ヒープ長} の Object.
*/
Zlib.Heap.prototype.pop = function() {
var index, value,
heap = this.buffer, swap,
current, parent;
value = heap[0];
index = heap[1];
// 後ろから値を取る
this.length -= 2;
heap[0] = heap[this.length];
heap[1] = heap[this.length + 1];
parent = 0;
// ルートノードから下がっていく
while (true) {
current = this.getChild(parent);
// 範囲チェック
if (current >= this.length) {
break;
}
// 隣のノードと比較して、隣の方が値が大きければ隣を現在ノードとして選択
if (current + 2 < this.length && heap[current + 2] > heap[current]) {
current += 2;
}
// 親ノードと比較して親の方が小さい場合は入れ替える
if (heap[current] > heap[parent]) {
swap = heap[parent];
heap[parent] = heap[current];
heap[current] = swap;
swap = heap[parent + 1];
heap[parent + 1] = heap[current + 1];
heap[current + 1] = swap;
} else {
break;
}
parent = current;
}
return {index: index, value: value, length: this.length};
};
// end of scope
});
/* vim:set expandtab ts=2 sw=2 tw=80: */