代码来源:晴神《算法笔记》!!
堆是一颗完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。
基本操作
向下调整
完全二叉树叶子结点的个数为n/2(向上取整),在[1,n/2]范围内为非叶子结点。倒着枚举能够保证每个结点都是以其为根结点的子树中权值最大的结点,父结点一旦发现子结点的权值都比自己小就可以终止向下调整,这样downadj()才是合理的。
//high一般为堆最后一个元素的下标
void downadj(int low, int high){
int i = low, j = i * 2;
while(j <= high){
if(j + 1 <= high && heap[j+1] > heap[j]){
j = j+1;
}
if(heap[j] > heap[i]){
swap(heap[j],heap[i]);
i = j;
j = i * 2;
}
else{
break;
}
}
}
void createheap(){
for(int i = n/2; i >= 1; i--){
downadj(i, n);
}
}
//删除堆顶元素
void deletetop(){
heap[1] = heap[n--];
downadj(1, n);
}
向上调整
//添加一个元素一般放在数组最后,然后应进行向上调整
//low一般为1
void upadj(int low, int high){
int i = high, j = i/2;
while(j >= low){
if(heap[i] > heap[j]){
swap(heap[i], heap[j]);
i = j;
j = i/2;
}
else break;
}
}
//添加元素
void insert(int x){
heap[++n] = x;
upadj(1, n);
}
堆排序
void heapsort(){
createheap();
for(int i = n; i > 1; i--){
swap(heap[i], heap[1]);
downadj(1, i-1);
}
}