重温堆排序

郑重声明:本文99.99%转载自http://blog.csdn.net/morewindows/article/details/6709644/

快一年没碰堆排序了……在这里给自己 总结 搞晕一下。

*堆排序基于二叉堆

  • 二叉堆的定义

    二叉堆是完全二叉树或者是近似完全二叉树。

    二叉堆满足二个特性:

    1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

    2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

  • 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。下图展示一个最小堆:
  • 由于其它几种堆(二项式堆,斐波纳契堆等)用的较少,一般将二叉堆就简称为堆。
  • 一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。上图:
  • 堆的插入、删除

  • 堆的插入:
 1 //  新加入i结点  其父结点为(i - 1) / 2
 2 void MinHeapFixup(int a[], int i)
 3 {
 4     int j, temp;
 5
 6     temp = a[i];
 7     j = (i - 1) / 2;      //父结点
 8     while (j >= 0 && i != 0)
 9     {
10         if (a[j] <= temp)
11             break;
12
13         a[i] = a[j];     //把较大的子结点往下移动,替换它的子结点
14         i = j;
15         j = (i - 1) / 2;
16     }
17     a[i] = temp;
18 }  
  • 堆的删除:

    代码和以上类似,就不赘述了。但是要注意:堆的插入是从下至上,堆的删除是从上至下!堆的删除要寻找子节点中最小或最大的节点,与其替换,重复这个步骤直至自己在子节点中最小。这样,堆才是可维护的。

以上是对堆的基础知识与操作。下面是堆排序的流程

  • 堆化数组(堆排序第一步)

  堆化数组只有一个方法——对堆中的元素进行向下调整(类似于堆的删除,只不过把根节点换成了普通节点)。而且调整的顺序是从下至上!!!

  这就相当于把更大(或更小)的数据换了上来,一直换到堆的最上方。而那些次要的数据就被留在下面。

实现代码:

1 //建立最小堆
2 void MakeMinHeap(int a[], int n)
3 {
4     for (int i = n / 2 - 1; i >= 0; i--)
5         MinHeapFixdown(a, i, n);
6 }  
  • 堆交换(堆排序第二步)

  每次提取堆的根节点,然后对堆进行一次删除操作。这样可把次大的节点换上来……

1 void MinheapsortTodescendarray(int a[], int n)
2 {
3     for (int i = n - 1; i >= 1; i--)
4     {
5         Swap(a[i], a[0]);
6         MinHeapFixdown(a, 0, i);
7     }
8 }  

這樣就夶功告成叻

(当然还要输出啦^(* ̄(oo) ̄)^)

╭︿︿︿╮
{/ o o /}  
 ( (oo) )   
 ︶ ︶︶    {The king of the pig}

时间: 2024-10-12 17:58:16

重温堆排序的相关文章

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

排序——堆排序算法

堆排序利用的完全二叉树这种数据结构所设计的一种算法,不过也是选择排序的一种. 堆实质上是满足如下性质的完全二叉树:k[i]<=k[2*i]&&k[i]<=k[2*i+1]或者k[i]>=k[2*i]&&k[i]>=k[2*i+1], 树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字. 堆分大顶堆和小顶堆:k[i]<=k[2*i]&&k[i]<=k[2*i+1]是小顶堆,k[i]>=k[2

排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题

常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结束.时间复杂度:O(n^2) 选择排序:每次在无序队列中"选择"出最大值,放到有序队列的最后,并从无序队列中去除该值(具体实现略有区别).时间复杂度:O(n^2) 直接插入排序:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的 移动数据,空出一个适当的位置,把待插

[算法学习笔记]排序算法——堆排序

堆排序 堆排序(heapsort)也是一种相对高效的排序方法,堆排序的时间复杂度为O(n lgn),同时堆排序使用了一种名为堆的数据结构进行管理. 二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树.二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆. 如上图显示,(a)是一个二叉堆(最大堆), (b)是这个二叉堆在数组中的存储形式. 通过给个一个节点的下标i, 很容易计算出其父节点,左右子节点的的下标,为了方便,

排序算法三:堆排序(Heapsort)

堆排序(Heapsort)是一种利用数据结构中的堆进行排序的算法,分为构建初始堆,减小堆的元素个数,调整堆共3步. (一)算法实现 1 protected void sort(int[] toSort) { 2 buildHeap(toSort); 3 for (int i = toSort.length - 1; i > 0; i--) { 4 CommonUtils.swap(toSort, 0, i); 5 adjustHeap(toSort, 0, i); 6 } 7 } 8 9 /**

算法----堆排序(heap sort)

堆排序是利用堆进行排序的高效算法,其能实现O(NlogN)的排序时间复杂度,具体算法分析可以点击堆排序算法时间复杂度分析. 算法实现: 调整堆: void sort::sink(int* a, const int root, const int end) { int i=root; while(2*i +1 <= end) { int k = 2*i+1; if(k+1<=end && a[k]<a[k+1]) k++; if(a[k] < a[i]) break;

快速排序和堆排序

1.快速排序 快速排序是不稳定的排序算法,平均时间复杂度O(nlgn).快速排序是利用了partition( )进行排序的.partition( )有两种实现形式,(1)利用两个指针一个头指针,一个尾指针,通过交换头尾指针所指的数进行排序; (2)一前一后两个指针同时从左往右进行遍历,如果前指针所遇到的数比主元小,则后指针右移一位,然后交换.Partition方法还可以用在很多地方,注意举一反三. //quicksort 时间复杂度O(n^2),不稳定排序 void quicksort (int

阿布学排序之堆排序

/** * 需求:堆排序的实现 * 知识储备: * 满二叉树:除叶子结点外的所有结点均有两个子结点,所有叶子结点必须在同一层上. * 完全二叉树: * 若二叉树的深度为h,除第h层外,其它各层(1~h-1)的节点数都达到最大个数,第h层所有结点都连续集中在最左边. * 完全二叉树是有满二叉树而引出来的,对于深度为K的,有N个结点的二叉树,当且仅当每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称它为完全二叉树. * * 二叉堆是完全二叉树或者是近似完全二叉树. * 二叉堆特性: *

面试必考三大排序算法C++代码(快速排序、归并排序、堆排序)

前两个为C++风格代码,后一个为C风格代码,除了输入输出,其它无差别,但C输入输出要比C++更快. 快速排序 1 #include <iostream> 2 using namespace std; 3 4 void swap(int num[], int i, int j) 5 { 6 int temp = num[i]; 7 num[i] = num[j]; 8 num[j] = temp; 9 } 10 11 int partition(int num[], int left, int