涉及到大根堆的知识点;
最小父节点为length/2-1
父节点的子节点为son = dad*2+1 或 dad*2+2
大根堆即所有父节点大于所有子节点
主要函数:
void Heap_Sort(int *a,int length)
{
int i;
//从最小的父亲节开始改变,使每一个父亲节点大于儿子节点,从而构成大根堆
for(int i = length/2-1;i >=0 ;--i)
{
Heap(a,i,length);
}
//排序完成后最开始的节点一定是最大的,因为是大根堆
swap(a[0],a[length-1]);
for(int i = length-1;i > 1;--i)
{
Heap(a,0,i);//因为大根堆父亲节点大于所有子节点,所以排序一次即可
swap(a[0],a[i-1]);
}
}
先将无序数组转换为大根堆
然后将首节点与最后节点交换,因为大根堆的头节点最大,这时候最末尾元素就是最大的了
然后在用heap一次即可找打剩余最大的数字持续交换直到剩下最后一个元素即可
次要函数:
//使每个父亲节点大于儿子节点
void Heap(int *a,int dad,int length)
{
int son = dad*2+1;
while(son < length)
{
if(son+1<length && a[son] < a[son+1])//保证儿子节点是两个儿子中最大的
{
++son;
}
if(a[dad] < a[son])
{
swap(a[dad],a[son]);
}
dad = son;
son = dad*2+1;
}
}
该函数只能使一个头节点的元素最大,需要从最小的父节点进行循环,因为如果从下往上的话最大的数传播不上去;在主函数后续只需要排序一次是因为:只有头节点不满足大根堆,相当于第一次的最后一步,也就是排序最后一个头节点,因此只需要排序一次即可构成大根堆;
c++代码如下:
#include <bits/stdc++.h>
using namespace std;
void swap(int &a,int &b)
{
int t = a;
a = b;
b = t;
}
//使每个父亲节点大于儿子节点
void Heap(int *a,int dad,int length)
{
int son = dad*2+1;
while(son < length)
{
if(son+1<length && a[son] < a[son+1])//保证儿子节点是两个儿子中最大的
{
++son;
}
if(a[dad] < a[son])
{
swap(a[dad],a[son]);
}
dad = son;
son = dad*2+1;
}
}
void Heap_Sort(int *a,int length)
{
int i;
//从最小的父亲节开始改变,使每一个父亲节点大于儿子节点,从而构成大根堆
for(int i = length/2-1;i >=0 ;--i)
{
Heap(a,i,length);
}
//排序完成后最开始的节点一定是最大的,因为是大根堆
swap(a[0],a[length-1]);
for(int i = length-1;i > 1;--i)
{
Heap(a,0,i);//因为大根堆父亲节点大于所有子节点,所以排序一次即可
swap(a[0],a[i-1]);
}
}
void print_arr(int *arr,int size)
{
for(int i = 0;i < size;++i)
{
cout << arr[i];
if(i != size-1)
{
cout << " ";
}
}
}
int main()
{
int n;
cin >> n;
int arr[n];
for(int i = 0;i < n;++i)
{
cin >> arr[i];
}
Heap_Sort(arr,n);
print_arr(arr,n);
cout << endl;
}