堆的建立
堆在很多方面都有运用,这里写一下将一个完全二叉树用一维数组保存后再转化为一个最小堆
代码如下(假如树中的数据都为整数)
#include<stdio.h>
int a[50];
int n;
void swap(int p,int q){//交换函数
int tmp;
tmp=a[p];
a[p]=a[q];
a[q]=tmp;
}
void siftdown(int i){//处理树的元素
int t,flag=0;
while(i*2<=n&&flag==0){//有左子结点
if(a[i]>a[i*2]) t=2*i;
else t=i;
if(i*2+1<=n){//有右子结点
if(a[t]>a[i*2+1]) t=2*i+1;
}
if(t!=i){//不相等则父结点大于某个更小的子结点
swap(t,i);//交换
i=t;//继续对这个数进行判断
}
else flag=1;//父结点小于子结点,循环结束
}
}
void creat(){//最小堆的建立函数
int i;
for(i=n/2;i>=1;i--){//最后一层无需判断
siftdown(i);
}
}
int main()
{
int i;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
creat();
return 0;
}
以上就是将一个完全二叉树转化为最小堆的过程,下面再介绍在最小堆建立完成后的堆排序
堆排序
直接进入代码部分
#include<stdio.h>
int a[50];
int n;
void swap(int p,int q){//交换函数
int tmp;
tmp=a[p];
a[p]=a[q];
a[q]=tmp;
}
void siftdown(int i){//处理树的元素
int t,flag=0;
while(i*2<=n&&flag==0){//有左子结点
if(a[i]>a[i*2]) t=2*i;
else t=i;
if(i*2+1<=n){//有右子结点
if(a[t]>a[i*2+1]) t=2*i+1;
}
if(t!=i){//不相等则父结点大于某个更小的子结点
swap(t,i);//交换
i=t;//继续对这个数进行判断
}
else flag=1;//父结点小于子结点,循环结束
}
}
void creat(){//最小堆的建立函数
int i;
for(i=n/2;i>=1;i--){//最后一层无需判断
siftdown(i);
}
}
int del(){//取出堆顶元素并删除
int t;
t=a[1];
a[1]=a[n];
n--;
siftdown(1);
return t;
}
int main()
{
int i,t;
scanf("%d",&n);
t=n;
for(i=1;i<=n;i++) scanf("%d",&a[i]);
creat();
for(i=1;i<=t;i++) printf("%d ",del());
return 0;
}
堆排序的时间复杂度和快速排序一样,也是O(NlogN)