`
king_tt
  • 浏览: 2108303 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

【算法导论】排序 (二):堆排序

 
阅读更多

四、(1)堆排序

第一次听堆排序是在107lab听忠哥讲的,但是没讲怎么实现。那时刚看了数据结构的二叉树,还以为要通过指针建立二叉树的方式来实现,觉得挺难的。


其实堆排序实现没有想象中的那么难。


“堆”这个词最初是在堆排序中提出来的,但后来就逐渐指”废料收集储存区“,就像程序设计语言Lisp和Java中所提供的设施那样。我们这里的堆数据结构不是废料收集存储区。


堆排序的运行时间与归并排序一样为O(n lg n), 但是一种原地(in place)排序。

(二叉)堆数据结构是一种数组对象,它可以被视为一棵完全二叉树。

对于一个数组arr[ ]={16,14,10,8,7,9,3,2,4,1}的存储数据结构如下图:


在这个结构中,对于每一个根节点i ,要保证它都比他的子节点大


我们可以用一个数组A【1...length【A】】来表示这个完全二叉树结构。 其中A【1】为根节点1

首先问题是求父节点、左儿子、右儿子的坐标,通过观察我们可以用宏或者内联函数实现:


  1. //根据某节点下标i,计算父节点、左儿子、右儿子的下标
  2. inlineintParent(inti){returni>>1;}
  3. inlineintLeft(inti){returni<<1;}
  4. inlineintRight(inti){return(i<<1)|1;}//位运算乘2后,结果是偶数所以最后一位一定是0,所以|1将会把最后一位变成1,从而实现加1的效果

无论是《C++ primer》还是《Effective C++》,都讲过宏的缺陷,用内联函数是个更好的选择。位运算做乘除的速度更快。

至于算法演示过程在《算法导论》上讲得很详细,不再赘述。

堆排序过程需要以下三个函数:

1、Max-Heapify(A,i): 保持堆的性质,让A【i】在最大堆中“下降”,使以i节点为根的字数成为最大树


2、Buid-Max-Heap(A)自底向上将数组A【1...n】变成一个最大堆


3、Heap-Sort(A): 进行堆排序

C++代码实现:(数组A是下标1开始的)

  1. /*算法导论第6章堆排序*/
  2. #include<cstdio>
  3. #include<algorithm>
  4. usingnamespacestd;
  5. //根据某节点下标i,计算父节点、左儿子、右儿子的下标
  6. inlineintParent(inti){returni>>1;}
  7. inlineintLeft(inti){returni<<1;}
  8. inlineintRight(inti){return(i<<1)|1;}//位运算乘2后,结果是偶数所以最后一位一定是0,所以|1将会把最后一位变成1,从而实现加1的效果
  9. inlinevoidSwap(int&a,int&b){if(a!=b){a^=b;b^=a;a^=b;}}
  10. /*
  11. 堆排序的基本过程函数:
  12. MaxHeap(A,len,i):其运行时间为O(lgN),是保持最大堆性质的关键
  13. BuidMaxHeap(A):过程,以线性时间运行,可以在无需的输入数组基础上构造出最大堆
  14. HeapSort(A):对一个数组原地进行排序
  15. */
  16. //保持堆的性质,使以i为根的子树成为最大堆
  17. voidMaxHeap(int*A,intheap_size,inti){
  18. intl,r,max;
  19. l=Left(i);
  20. r=Right(i);
  21. if(l<=heap_size&&A[l]>A[i])
  22. max=l;
  23. else
  24. max=i;
  25. if(r<=heap_size&&A[r]>A[max])
  26. max=r;
  27. if(max!=i){
  28. Swap(A[i],A[max]);
  29. MaxHeap(A,heap_size,max);
  30. }
  31. }
  32. //建堆,自底向上用MaxHeap将整个数组变成一个最大堆
  33. voidBuidMaxHeap(int*A,intheap_size){
  34. for(inti=heap_size>>1;i>=1;--i){
  35. MaxHeap(A,heap_size,i);
  36. }
  37. }
  38. //堆排序
  39. voidHeapSort(int*A,intheap_size){
  40. BuidMaxHeap(A,heap_size);
  41. intlen=heap_size;
  42. for(inti=heap_size;i>=2;--i){
  43. Swap(A[1],A[i]);
  44. --len;
  45. MaxHeap(A,len,1);
  46. }
  47. }



(2)优先级队列

C++ STL中的priority_queue就是用这种方法来实现的。

1、Heap-MaxiNum(A): 取出堆中的最大值




2、Heap-Extract-Max(A):删除堆中的最大值并返回它的值




3、Heap-Increase-Key(A,i,key):将节点i的值增加到key,这里key要比i节点原来的数大。




4、Max-Heap-Insert(A, key): 插入一个新元素key到堆中,要用到3的函数



C++实现:

  1. //优先级队列
  2. intHeapMaxNum(int*A){
  3. returnA[1];
  4. }
  5. intHeapExtractMax(int*A,intheap_size){
  6. if(heap_size>=1){
  7. intmax=A[1];
  8. A[1]=A[heap_size];
  9. --heap_size;
  10. MaxHeap(A,heap_size,1);
  11. returnmax;
  12. }
  13. }
  14. boolHeapIncreaseKey(int*A,inti,intkey){
  15. if(key<A[i])
  16. returnfalse;
  17. A[i]=key;
  18. while(i>1&&A[Parent(i)]<A[i]){
  19. Swap(A[i],A[Parent(i)]);
  20. i=Parent(i);
  21. }
  22. returntrue;
  23. }
  24. voidMaxHeapInsert(int*A,intkey,intheap_size){
  25. ++heap_size;
  26. A[heap_size]=-2147484646;
  27. HeapIncreaseKey(A,heap_size,key);
  28. }

—— 生命的意义,在于赋予它意义。

原创http://blog.csdn.net/shuangde800By D_Double





分享到:
评论

相关推荐

    【算法导论】排序算法源码

    自学算法导论中前几章,并自己...二、快速排序、分治法排序、堆排序 http://blog.csdn.net/ceofit/article/details/7442874 三、计数排序、基数排序、桶排序 http://blog.csdn.net/ceofit/article/details/7447547 ...

    算法导论中堆排序c++源程序

    算法导论上的堆排序c++源程序||学习分享

    堆排序代码 《算法导论》

    参考《算法导论》这本书写的一个堆排序的代码,我个人是用Visual studio写的。只要一个积分哦

    算法导论 快速排序 堆排序 代码 可运行

    算法导论 快速排序 堆排序 算法导论上的算法实现更加精简高效 代码可编译运行测试 加了测试用例 加了注释

    堆排序算法导论

    实现算法导论中的堆排序,区别数组以0作为根,算法导论中的实现是以数组1作为根

    算法导论排序算法汇总

    算法导论中第二章所有排序的自己模拟,快速排序,堆排序,计数排序,最大最小数,选择第n个数等等

    算法导论第三版各种排序算法的c/c++实现

    请参考算法导论第三版英文版Introduction to Algorithms 3rd Edition,本程序为第一章到第八章重要...堆排序 快速排序(2中分割方法) 随机化快速排序 TAIL-RECURSIVE-QUICKSORT Counting sort Radix sort 二分法搜索

    算法导论 第二版 (完整版)

    第6章 堆排序 第7章 快速排序 第8章 线性时间排序 第9章 中位数和顺序统计学 第三部分 数据结构 第10章 基本数据结构 第11章 散列表 第12章 二叉查找树 第13章 红黑树 第14章 数据结构的扩张 第四部分 高级设计和...

    php堆排序(算法导论)

    php堆排序(算法导论)

    堆排序最大堆【算法导论】

    ps:按照书中伪码写成,元素由1开始,故数组中第一位A[0]为填充,并不算在排序中。 for(int i = length; i &gt;= 2;) { temp = A[i]; //交换堆的第一个元素和堆的最后一个元素 A[i] = A[1]; A[1] = temp; i--; //...

    堆排序(C#,C++)算法导论

    算法导论第三版第六章内容,作者使用C#与C++两种编程语言实现

    堆排序(最大堆修改版)【算法导论】

    上个资源的有效排序下标是由1开始的,0只做了填充作用,这次则由下标0为根节点: for(int i = length; i &gt;= 1;) //最后一个肯定是最小的 { temp = A[i]; //交换堆的第一个元素和堆的最后一个元素 A[i] = A[0]; ...

    堆排序算法实例

    算法导论上堆排序算法的vc6.0下的Test实例。

    算法导论(第2版)参考答案

     第六章 堆排序(Heapsort)  第七章 快速排序(Quicksort)  第八章 线性时间中的排序(Sorting in Linear Time)  第九章 中值与顺序统计(Medians and Order Statistics)  第三部分(Part III) 数据结构...

    算法导论 Thomas H.Cormen

    •移除两章很少讲授的内容:二项堆和排序网络。 •修订了动态规划和贪心算法相关内容。 •流网络相关材料现在基于边上的全部流。 •由于关于矩阵基础和Strassen算法的材料移到了其他章,矩阵运算这一章的内容所占...

    堆排序算法实现

    根据算法导论第六章实现的堆排序

    算法导论学习资料共享

    包括源码:常用排序算法(插入、堆、归并、快速)、装配线问题、最长公共子序列问题、矩阵连乘问题、 优先队列、huffman编码、贪心算法,全部用Java实现的。 算法导论答案

    算法导论 第三版 中文版

    3、移除两章很少讲授的内容:二项堆和排序网络。 4、修订了动态规划和贪心算法相关内容。 5、流网络相关材料现在基于边上的全部流。 6、由于关于矩阵基础和Strassen算法的材料移到了其他章,矩阵运算这一章的内容所...

    插入排序,合并排序,堆排序,快速排序,计数排序c++实现

    这些代码是对算法导论上对排序部分的总结,实现了以下排序方法:插入排序,合并排序,堆排序,快速排序,计数排序,每种实现都有详细的注释和相应的测试程序,可查找http://blog.csdn.net/china8848&lt;br&gt;中对相关问题...

    算法导论 第三版 中文版 第二部分

     移除两章很少讲授的内容:二项堆和排序网络。  修订了动态规划和贪心算法相关内容。  流网络相关材料现在基于边上的全部流。  由于关于矩阵基础和strassen算法的材料移到了其他章,矩阵运算这一章的内容所占...

Global site tag (gtag.js) - Google Analytics