堆排序问题
在说堆排序之前,必须得弄清楚什么是堆?堆就是一种特殊的完全二叉树,而它具有一些特点。堆又分为最小堆和最大堆,如果所有的父节点都比子节点小,则这样的堆称为最小堆,反之,则为最大堆。我们开始先创建一个最小堆,首先我们从叶节点开始,因为叶节点没有儿子,所以所有的叶节点都符合最小堆特征。于是就得从最后一个非叶节点开始,直到根节点,逐渐调整它们的位置。
创建堆代码如下:
void create()
{
for(int i = n / 2; i >= 1; i --)
shiftdown(i);
return;
}
shiftdown函数作用便是调整位置,从父节点开始,若发现它最小的子节点的值比它还小,便把它和父节点交换位置,直到父节点为叶节点为止。
void shiftdown(int i)
{
int t ,flag = 0;
while(i * 2 <= n && flag == 0)
{
if(h[i] > h[i * 2])
t = i * 2;
else
t = i;
if(i * 2 + 1 <= n )
{
if(h[t] > h[i * 2 + 1])
t = i * 2 + 1;
}
if(t != i)
{
swap(i,t);
i = t;
}else
flag = 1;
}
return;
}
还有一个问题,如何让它由小到大排序输出呢?可以每次输出h[1]后,把最后一个叶节点赋值给h[1],再重新调整位置即可。输出过后每次删除一个节点。
int deletemax()
{
int t;
t = h[1];
h[1] = h[n];
n --;
shiftdown(1);
return t;
}
main函数如下:
int main()
{
int num;
cin >> n;
num = n;
for(int i = 1; i <= n; i ++)
scanf("%d",&h[i]);
create();
for(int i = 1; i <= num; i ++)
cout << deletemax() << " ";
return 0;
}
也可以先建立最大堆,最大元素在h[1],我们的需求是从小到大排序,希望最大的放在最后。因此我们把h[1]和h[n]交换,因此h[n]便是最大的数,交换后h[1]相下调整以保持堆得特性。
排序函数如下:
void heapsort()
{
while(n > 1)
{
swap(1,n);
n --;
shiftdown(1);
}
}
main函数如下:
int main()
{
int num;
cin >> n;
num = n;
for(int i = 1; i <= n; i ++)
scanf("%d",&h[i]);
create();
heapsort();
for(int i = 1; i <= num; i ++)
cout << h[i] << " ";
return 0;
}
学了堆排序,发现最大好处就是效率高。