堆排序
来源:互联网 发布:在线汇率查询php代码 编辑:程序博客网 时间:2024/06/11 20:54
堆排序一直没有搞的很明白!今天总算搞定了。其实核心在于“堆的调整”。接口形如adjust_heap(*p, int n, int i),一个T类型的,长度为n的数组,将以i为根节点的子树调整为大顶堆或者小顶堆。原理可以这么想:根节点T[i]有左孩子T[2*i+1]和右孩子T[2*i+2],假如左孩子已经是一个大顶堆,右孩子也是大顶堆,而且:
T[i] > T[2*i+1]
T[i] > T[2*i+2]
那么,根据堆的定义,T[i]就是一个大顶堆了。
堆排序首先定义了这么一个“堆的调整”操作,随后的算法都是基于此的。堆以数组存储,a[N],最后一个元素为a[N-1],其父节点为a[(N-1-1)/2],将a[(N-1-1)/2]调整为大顶堆,然后向前走,将a[(N-1-1)/2-1]、a[(N-1-1)/2-2]、。。。a[2]、a[1]、a[0]调整为大顶堆。最后整个数组是一个大顶堆。
随后删除元素。删除堆顶,将a[0]与最后一个元素a[N-1]交换,此时a[N-1]为最大值,随后对a[0]至a[N-2]范围的元素做“堆的调整”操作,调整为堆后,又删除堆顶,得到第二大的元素。。。。最后数组呈现递增排列。
所谓“堆的调整”就是,左孩子和右孩子都已经是堆了,根节点是新来的,此时需要自上而下调整一遍。
复杂度:一次堆的调整为log(n),建堆需要n Log(n)。删除元素为O(1),重新调整N次,复杂度也是n*log(n),最终复杂度为n*log(n)。
// 堆排序// 堆的调整、建堆、删除#include <stdio.h>#include <stdlib.h>template<typename T>int is_heap(T *tp, int nLen);template<typename T>void adjust_heap(T *tp, int nLen, int pos);template<typename T>void make_heap(T *tp, int nLen);template<typename T>void heap_sort(T *tp, int nLen);const int N=20;int main(){int ap[N];int i;for (i=0;i<N;i++){ap[i]=rand()%100;printf("%d ", ap[i]);}printf("\n");heap_sort(ap,N);printf("排序后:\n");for (i=0;i<N;i++){printf("%d ", ap[i]);}printf("\n");return 0;}//----------------------------------------// 交换元素template<typename T>void _swap(T &a, T&b){T tmp;tmp=a;a=b;b=tmp;}// 堆的调整template<typename T>void adjust_heap(T *tp, int nLen, int pos){int i=pos;int j=2*i+1;for ( ;j<nLen; ){if (j+1<nLen && tp[j+1]<tp[j])j++;if (tp[i] < tp[j]){break;}_swap(tp[i], tp[j]);i=j;j=2*j+1;}}// 建堆template<typename T>void make_heap(T *tp, int nLen){int i;for (i=(nLen-1-1)/2; i>=0; i--){adjust_heap(tp, nLen, i);}if (is_heap(tp,nLen)){printf("IS a HEAP\n");}else{printf("NOT a HEAP\n");}}// 排序template<typename T>void heap_sort(T *tp, int nLen){make_heap(tp, nLen);int i;for (i=nLen-1; i>=1; i--){_swap(tp[0], tp[i]);adjust_heap(tp, i, 0);}}// 判断是否为堆template<typename T>int is_heap(T *tp, int nLen){int i;for (i=0; 2*i+1<nLen; i++){if (tp[i]>tp[2*i+1])return 0;if (2*i+2<nLen && tp[i]>tp[2*i+2])return 0;}return 1;}
ref:
http://blog.csdn.net/fly_yr/article/details/8550701
http://blog.sina.com.cn/s/blog_5115d58c0100vr26.html
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- 一个小程序,让你知道Qt一次能支持按下多少个键(二)
- 大数据环境下集成R语言的数据挖掘平台项目记录(三)
- Ant_使用Ant 实现批量打包Android应用
- 张飞流水账:超级搞笑诠释人生哲理
- 2013.3.28 第一次面试总结
- 堆排序
- HDU 2601 An easy problem
- CFileDialog 使用 OFN_ALLOWMULTISELECT 标志选择多个文件
- the algorithms to solve the question X^N
- 谷歌地图
- 高速发展的中国的社会问题,潜在超级大国和未来经济大势
- USACO报告:chapter1.1:Your Ride Is Here
- C++ 学习使用 MFC CFileDialog
- powershell basic