- 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
136 lines
3.1 KiB
JavaScript
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: */
|