1.堆(完全二叉树)中寻找位置需要的三个重要的公式
1.结点 i 的父节点为(i-1)/2 (除根节点外)
2.结点 i 的左子女为 2i+1
3.结点 i 的右子女为 2i+2
2.下滑调整算法siftdown与最大堆的建立
下滑调整算法只对局部范围有效。也就是对当前子树(父节点,左孩,右孩)有效,只有进行了交换,算法才会往下滑,所以利用siftdown进行堆建立时,必须从堆的最后一个子树开始(最后一个父节点),逐步向上调整至根节点
void siftDown(vector<int> V,int begin, int end) {
int i = begin, j = 2 * i + 1;
int temp = V[i];
while (j <= end) {
if (j < end && heap[j] > heap[j + 1]) j++; //j指向左右子女中的较大值
if (V[i] >= V[j]) break; //当前子树不需要调整直接跳过
else { //需要往下调整
V[i] = V[j];
i = j;
j = 2 *i + 1;
}
V[i] = temp;
}
}
3.基于siftdown的最大堆排序算法
思想:利用最大堆的堆顶元素最大的特点,不断的把堆顶元素往后放
1.首先建立一个最大堆。
2.堆顶元素必然是该堆最大的,那么将该元素与最后一个元素交换,然后对前n-1个元素重新调整为最大堆,再依次进行上述步骤。
void HeapSort(vector<int> heap){
for(int i = (heap.size()-1-1)/2;i >= 0;i--) //从最后一个父节点开始
siftDown(heap,i,heap.size()-1); //建立一个最大堆
for(int i = heap.size()-1;i >= 0;i--)
swap(0,i); //堆顶依次排到最后面
siftDown(0,i-1); //作用:选出堆顶,即前面i-1个元素的最大值
}