首页 > 编程语言 > 详细

C++实现堆排序

时间:2014-08-27 23:30:18      阅读:487      评论:0      收藏:0      [点我收藏+]

堆排序是一种具有合并排序和插入排序共同优点的排序方法。它的时间复杂度为O(nlgn),它也是一种原地排序算法:在任何时候,数组中只有常数个元素存储在输入数组以外。要介绍堆排序首先要介绍什么是堆。

1.建堆:堆数据结构是一种数组对象,它可以被视为一颗完全二叉树,如下图。右边数组表示的堆可以用左边的完全二叉树来表示,其中若父节点对应数组下标为i,则其左孩子对应数组下标为2*i,右孩子为2*i+1。

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

具体代码如下:

void buildMaxHeap(int a[] , int heapSize){
for(int i = heapSize/2;i >= 1;--i)
max_heapify(a,i,heapSize); //本行代码调用max_heapify函数来保持最大堆性质,接下来会介绍到。heapSize为堆大小。
}

2.保持根堆性质:接下来介绍大根堆与小根堆的区别。大根堆某个节点的值最多是和其父节点一样大。小根堆的组织刚好相反。在堆排序中我们使用的是大根堆。为了保持大根堆的性质,我们假设从下标为i的数组元素开始,将其值与它的左孩子和右孩子相比较,找出最大值对应的下标largest,如果largest恰好与i相等,则说明节点i保持了最大堆性质。否则交换下标为largest和i所对应的数组元素值,并且对下标为largest的元素继续进行“保持根堆性质”的操作。这么说可能有些太缺乏生动性,那么一起来看看这个过程吧:bubuko.com,布布扣

bubuko.com,布布扣



可以看到图中节点值为4的节点的保持根堆性质过程。代码如下:

void max_heapify(int a[],int i,int heapSize){
int lindex = 2*i,rindex = 2*i + 1,largest = 0;
if(lindex <= heapSize && a[lindex-1] > a[i-1])//判断左孩子和节点i的值谁大,将大值得下标保存为largest
largest = lindex;
else
largest = i;

if(rindex <= heapSize && a[rindex-1] > a[largest-1])//判断右孩子和节点largest的值谁大
largest = rindex;

if(largest != i){//如果largest不等于i
swap(a[i-1] , a[largest-1]);//交换
max_heapify(a,largest,heapSize);//继续对下标为largest、大小为heapSize的节点进行“保持根堆性质”
}
}

以下是swap函数:

void swap(int& first , int& second){
int tem = 0;
tem = first;
first = second;
second = tem;
}

3.堆排序算法:我用一个图来直观表示吧!

bubuko.com,布布扣

过程大致是将大根堆的根节点与最后一个叶子节点交换,然后缩小数组范围(即将heapSize减小),将最大值排除掉,最后对新的根节点进行“保持堆性质方法”,依次类推,代码如下:

bubuko.com,布布扣

void heapSort(int a[] , int heapSize){
buildMaxHeap(a , heapSize);//建堆
for(int i = heapSize;i >= 2;--i){
swap(a[0] , a[i-1]);//将根节点与最后的叶子节点交换
--heapSize;//缩小堆范围
max_heapify(a,1,heapSize);//保持堆性质

}
}

C++实现堆排序

原文:http://blog.csdn.net/yu_sun90/article/details/38877791

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!