您的位置:首页 > 其它

排序之堆排序

2018-03-22 22:14 197 查看








下面我们来看一个例子:





对上述解释:我们先将给出的序列从上到下从左到右排成一颗二叉树,然后将该树调整成一颗大根堆,调整成大根堆的过程是从叶子节点开始的,就拿图 a 来说,5 是 0 的左孩子,但是孩子比父亲节点的元素大,所以我们要进行交换,当交换完之后,我们可以得到 8 的孩子节点变成 9 和 5 了,然后 9 比 8 大,进行交换,然后 6 的孩子节点变成了 9 和 7,9 比 6 大,进行交换,交换之后对左子树造成了影响,因为 6 的孩子变成了 8 和 5, 8 比 6 大,然后进行交换,于是成了图 b 。



从调整的过程来看,我们要明白首先是从叶子节点先上调整,但是在叶子节点元素改变的过程中,也要注意对叶子节点的节点是否有影响,如果有影响,要及时做调整。
堆的调整宝宝们应该会了吧,那么排序的过程就是不断的让调整好的大根堆的根节点输出,然后将最后一个节点放到根节点的位置,再次进行调整,调整成大根堆之后,依然输出根节点,将最后一个节点放到根节点的位置,再次调整成大根堆。。。。。直到就剩一个节点。。。





相信各位经过上面的例子,都明白了堆排序的过程与原理,大根堆输出的是降序,那么对应的,小根堆输出的就是升序,小根堆的原理和大根堆一样,这里就不做重复讲解了,我们来看看部分代码实现部分吧(省去了头文件以及一些定义)!typedef struct //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据项,类型为InfoType
} RecType;/排序的记录类型定义

void sift(RecType R[],int low,int high) //调整堆得过程、筛选
{
int i=low,j=2*i; //R[j]是R[i]的左孩子
RecType temp=R[i];
while (j<=high)
{
if (j<high && R[j].key<R[j+1].key) //若右孩子较大,把j指向右孩子
j++; //变为2i+1
if (temp.key<R[j].key)
{
R[i]=R[j]; //将R[j]调整到双亲结点位置上
i=j; //修改i和j值,以便继续向下筛选
j=2*i;
}
else break; //筛选结束
}
R[i]=temp; //被筛选结点的值放入最终位置
}

void HeapSort(RecType R[], int n)
{
int i;
RecType tmp;
for(int i=n/2;i>=1;i--) //循环建立初始堆
sift(R,i,n);
for(int i=n;i>=2;i--)//进行n-1趟堆排序,每趟堆排序的元素个数减1
{
tmp=R[1]; //将最后一个元素同当前区间内R[1]对换
R[1]=R[i];
R[i]=tmp;
sift(R,1,i-1); //筛选R[1]节点,得到i-1个节点的堆
}
}

int main()
{
int i,n=10;
RecType R[MaxSize];
KeyType a[]={3,2,9,5,4,7,6,1,0,8};
for (i=0;i<n;i++)
R[i].key=a[i];
printf("排序前:");
for (i=0;i<n;i++)
printf("%d ",R[i].key);
printf("\n");
HeapSort(R,n);
printf("排序后:");
for (i=0;i<n;i++)
printf("%d ",R[i].key);
printf("\n");
}

好了!就讲到这里了,有哪里不明白的小伙伴可以留言哦!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐