// 索引堆
function swap(arr, x, y) {
var temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
// 索引堆
存储结构为两个数组
第一个数组 为索引
第二个数组为 值
每次取最大值的时候,只改变索引结构 而值不变 这样保证了数据的一致性
class MaxHeap{
constructor(capacity) {
// indexes 索引数组
// Item 则是数据
// 在建堆的过程中 Item的值保持不变 变的是indexes数组内的值
this.Item = new Array(capacity + 1);
this.indexes = new Array(capacity + 1);
this.count = 0;
this.capacity = capacity;
}
// 返回 数据的大小
size() {
return this.count;
}
// 判断Item是否是 空的
isEmpty() {
return this.count == 0;
}
// 添加新元素
insert (item) {
// 这个可能会 数组越界
// 但是js自动可以添加
this.Item[this.count+1] = item;
this.indexes[this.count+1] = this.count +1;
this.count++;
this.shiftUp(this.count)
}
shiftUp(count) {
// 判断父节点 是否比自身节点 大
while( count > 1 && this.Item[this.indexes[Math.floor(count/2)]] < this.Item[this.indexes[count]]) {
swap(this.indexes, Math.floor(count/2), count );
count = Math.floor(count/2);
}
}
// 出堆
extractMax() {
if( this.count > 0){
// 获取大顶堆的值
// num 为大顶堆的最大值 的序号
var num = this.indexes[1]
var x = this.Item[num];
this.indexes[1] = this.indexes.pop();
this.count--;
this.shiftDown(1)
return x;
}
return null;
}
shiftDown(k) {
while( 2*k <= this.count) {
var j = 2*k;
//如果右节点 存在且大于左节点 则j = j+1
if( j+1 <= this.count && this.Item[this.indexes[j+1]] > this.Item[this.indexes[j]]) {
j = j+1;
}
// 如果父节点 大于子节点最大值 则跳出循环
if( this.Item[this.indexes[k]] > this.Item[this.indexes[j]]) {
break;
}
swap(this.indexes, k, j);
k=j;
}
}
}
//生成一个数组
function generate(n, rangeL, rangR){
var arr = []
for(var i=0; i<n; i++){
var x = Math.floor(Math.random() * (rangR -rangeL+1)) + rangeL;
arr.push(x);
}
return arr;
}
function heapSort(arr, n) {
var max = new MaxHeap(n);
for(var i=0; i<n; i++) {
max.insert(arr[i]);
}
for(var i=n-1; i>=0; i--) {
arr[i] = max.extractMax();
}
console.log(max.indexes);
console.log(max.Item)
console.log(arr)
}
var arr = generate(10, 0, 10);
heapSort(arr, 10);