大顶堆建堆方式
· 第一种
将所有待排序元素输入后开始排序
//需要实现down的调整,即将某个位置是元素向下调整到其应该到的位置上
//调整顺序应该从倒数第二列开始,即最后一个元素的父节点开始
void adjustDown(vector<int>& a, int n, int parent){
int child = parent * 2 + 1;
if (child < n)
//当 孩子的下标 超出 数组的范围,则说明不存在
{
//1.选出左右孩子中,较小的一个
//child -- 左孩子下标;child+1 -- 右孩子下标
if (child + 1 < n && a[child + 1] < a[child])
{
//想象的时候:默认左孩子是比右孩子小
//如果大的话,child就走到右孩子下标处
child++;
}
//2.交换
if (a[child] < a[parent])
{
swap(a[child], a[parent]);
parent = child;
adjustDown(a, n, child);
}
}
}
下面是建堆代码:
int n = arr.size();
for(int i = (n - 1) / 2; i >= 0 ; i--){
adjustDown(arr, n,i);
}
· 第二种
将每一个元素放在最末尾,然后往上up
void adjustUp(vector<int> & a, int child){
int parent = (child - 1) / 2;
if(parent >= 0)
{
if(a[parent] > a[child]){
swap(a[parent], a[child]);
adjustUp(a, parent);
}
}
}
构建代码:
int n = arr.size(); //arr里面是无序的
vector<int> temp;
for(int i = 0; i < n; i++){
temp.push_back(arr[i]);
adjustUp(temp, i);
}
排序输出:
堆排序的数组中,并不能直接有序输出,而是要先输出第一个,然后把第一个和最后一个元素交换,让交换了以后的堆头元素down到合适的位置。这个方式每次只能输出一个元素,但能保证是目前数组中最大的或者是目前数组中最小的。
代码:
for(int i = 0; i < n; i ++)
{
cout << temp[0] <<' ';
swap(temp[0], temp[temp.size() - 1]);
temp.pop_back();
adjustDown(temp, temp.size(), 0);
}
例题:最小的前k个数