`
king_tt
  • 浏览: 2259602 次
  • 性别: 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++源程序||学习分享

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

    根据提供的信息,《算法导论(第2版)参考答案》这本书涵盖了计算机科学中算法的核心概念和技术,本书由多个章节组成,下面将详细解释各部分的关键知识点。 ### 第一部分:基础 #### 第一章:计算中算法的角色 - *...

    算法导论Lecture 4:Quicksort

    在算法导论中,关于快速排序的研究通常会涉及以下几个方面: 1. 快速排序算法的基本原理和步骤。 2. 如何选择基准元素来提高算法效率,比如随机选择、中位数法等。 3. 快速排序算法的变种,例如三数取中法、迭代...

    算法导论_完整课件:算法导论_完整课件

    2. **排序与搜索算法**:排序算法(如快速排序、归并排序、堆排序)和搜索算法(如二分查找、线性查找)是基础中的基础,讲座04和05可能详细讲解这些内容,同时还会探讨它们的效率和适用场景。 3. **图算法**:讲座...

    算法导论第二版课后答案中文完全版

    快速排序、归并排序、堆排序、二分查找、广度优先搜索和深度优先搜索等经典算法的解答,有助于读者深入理解它们的工作原理,从而能够熟练运用在实际编程中。 递归和递推是算法设计中的常见技巧,答案中对这些问题的...

    算法导论 中文 第三版 高清

    1. 排序算法:包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等,它们用于将无序的数据序列按照特定规则进行排列,是计算机科学中最基本的算法之一。 2. 搜索算法:如二分查找、广度优先搜索(BFS)...

    堆排序代码 《算法导论》

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

    算法导论中文版

    4. 排序算法:介绍各种经典的排序算法,如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序和基数排序等,分析它们的效率及应用场景。 5. 搜索算法:讲解线性搜索、二分搜索等基础搜索技术,以及散列表和...

    算法导论中文版第二版(书+课后习题答案)

    2. 排序算法:插入排序、选择排序、冒泡排序属于基础排序,而快速排序、归并排序、堆排序等更高效的方法则更适合大数据量处理。 四、高级算法 1. 回溯法和分支限界法:用于解决组合优化问题,如八皇后问题、N-...

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

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

    算法导论习题解. \算法导论习题解.

    根据提供的文件信息,可以看出这是一份关于《算法导论》一书习题解答的手稿或文档。虽然部分内容不太清晰,但从目录和前言部分可以推测出文档的主要内容是围绕算法的基础概念、排序算法以及相关算法分析展开的。下面...

    算法导论排序算法汇总

    《算法导论》是一本广泛认可的经典教材,深入浅出地介绍了各种算法,包括排序算法。在这里,我们将详细探讨其中涉及的几种排序算法:快速排序、堆排序、计数排序以及如何找到最大最小数和第n个数。 首先,**快速...

    算法导论第四版 英文

    《算法导论第四版》系统地介绍了多种排序算法,如冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序等。书中不仅解释了每种算法的工作原理和性能特性,还对比了它们在不同情况下的应用效果。此外,作者还...

    算法导论第二版答案及介绍

    《算法导论》第二版是计算机科学领域的一本经典教材,由Thomas H. Cormen、Charles E. Leiserson、Ronald L. Rivest和Clifford Stein合著。这本书全面覆盖了算法的设计、分析和实现,是学习算法的必备参考书。其中...

    算法导论试题及答案

    1. **排序算法**:包括冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序等,以及它们的时间复杂度和适用场景。 2. **搜索算法**:二分查找、广度优先搜索(BFS)、深度优先搜索(DFS)等,以及在图和树...

    算法导论第二版答案

    根据提供的文件内容,可以看出这是一份《算法导论》(第二版)的教师手册,它旨在配合Thomas H. Cormen、Charles E. Leiserson、Ronald L. Rivest和Clifford Stein共同编写的《Introduction to Algorithms》(第二版...

    算法导论(英文第四版)非扫描

    - **第六章:堆排序** - **6.1 堆的定义**:详细解释了堆数据结构的概念及其性质。 - **6.2 维护堆属性**:介绍了如何保持堆的数据结构属性不变。 #### 三、算法的重要性 《算法导论》之所以成为经典教材,是...

    算法导论答案算法导论教师手册

    《算法导论》详细讲解了各种排序算法,包括冒泡排序、插入排序、选择排序、归并排序、快速排序和堆排序。其中,快速排序以其高效性和通用性而著名,而堆排序则利用了二叉堆的数据结构,能够在O(n log n)时间内完成...

    《算法导论第二版》 习题答案

    ### 《算法导论第二版》习题答案解析 #### 一、概述 《算法导论第二版》是由Thomas H. Cormen、Charles E. Leiserson、Ronald L. Rivest以及Clifford Stein四位计算机科学领域的专家共同编写的经典教材。本书深入...

Global site tag (gtag.js) - Google Analytics