堆排序

来源:互联网 发布:单片机控制蜂鸣器发声 编辑:程序博客网 时间:2024/04/30 08:11

参考文章有很多,推荐:http://www.wutianqi.com/?p=1820

注:堆排序不是一种稳定排序。


堆排序方法对记录数较稍等文件并不值得提倡,但对n较大的文件还是很有效的。因为其运行时间主要耗费在建初始堆和调整建新堆时进行的反复“筛选”上。对深度为k的堆,筛选算法中进行的关键字比较次数之多为2(k-1)次,则在建含n个元素,深度为h的堆时,总共进行的关键字比较次数不超过4n。又,n个节点的完全二叉树的深度为lgn+1,则调整建新堆时调用heapadjust过程n-1次,总共进行的比较次数不超过O(nlogn).相对于快速排序来说,这是堆排序的最大优点。此外,堆排序仅仅需要一个记录大小供交换用的辅助存储空间。

代码如下:

#include<stdio.h>#include<algorithm>#include<cstring>#include<iostream>using namespace std;const int N = 10;int arr[N];int parent(int i){return i / 2;} //父节点int left(int i){return 2 * i;} //左子节点int right(int i){return 2 * i + 1;} //右子节点void heapadjust(int i, int n){int l, r, largest;l = left(i), r = right(i);if(l <= n && arr[l] > arr[i])largest = l;elselargest = i;if(r <= n && arr[r] > arr[largest])largest = r;if(largest != i){swap(arr[i], arr[largest]);heapadjust(largest, n); /*交换后子部分可能不满足堆性质,所以递归调整。堆:对任意一棵树的任意一个非叶子节点,该节点值应该大于等于(或小于)左右子节点的数据结构.若满足大于等于,则为大顶堆;反之为小顶堆*/}}/*初始调用buildheap将arr[1..n]变成最大堆因为数组最大元素在arr[1],则可以通过将arr[1]与a[n]互换达到正确位置现在新的根元素破坏了最大堆的性质,所以调用heapadjust调整,使arr[1..n-1]成为最大堆,arr[1]又是arr[1..n-1]中的最大元素,将arr[1]与arr[n-1]互换达到正确位置。反复调用heapadjust(1, i - 1),使整个数组成从小到大排序。*/void buildheap(int n) //自底向上是因为要使最大元素升至堆顶{for(int i = n / 2; i > 0; --i)heapadjust(i, n);}/*交换只是破坏了以a[1]为根的二叉树最大堆性质,它的左右子二叉树还是具备最大堆性质。这也是为何在build_maxheap时需要遍历n/2到1的结点才能构成最大堆,而这里只需要堆化arr[1]即可。*/void heap_sort(int n){buildheap(n);for(int i = n; i > 1; --i) //n-1次之后排序完成{swap(arr[1], arr[i]);heapadjust(1, i - 1);}}int main(){for(int i = 1; i <= 10; ++i)scanf("%d", &arr[i]);heap_sort(10);for(int i = 1; i <= 10; ++i)cout<<arr[i]<<" ";cout<<endl;return 0;}



原创粉丝点击