在软件设计相关领域,“堆(Heap)”的概念主要涉及到两个方面:

一种是数据结构,逻辑上是一颗完全二叉树,存储上是一个数组对象(二叉堆)。

另一种是垃圾收集存储区,是软件系统可以编程的内存区域。

本文所说的堆指的是前者,另外,这篇文章中堆中元素的值均以整形为例

堆排序的时间复杂度是O(nlog2n),与快速排序达到相同的时间复杂度. 但是在实际应用中,我们往往采用快速排序而不是堆排序. 这是因为快速排序的一个好的实现,往往比堆排序具有更好的表现. 堆排序的主要用途,是在形成和处理优先级队列方面. 另外, 如果计算要求是类优先级队列(比如, 只要返回最大或者最小元素, 只有有限的插入要求等), 堆同样是很适合的数据结构.

 

堆排序
堆排序是一种选择排序。是不稳定的排序方法。时间复杂度为O(nlog2n)。
堆排序的特点是:在排序过程中,将排序数组看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录。

基本思想
1.将要排序的数组创建为一个大根堆。大根堆的堆顶元素就是这个堆中最大的元素。
2.将大根堆的堆顶元素和无序区最后一个元素交换,并将无序区最后一个位置例入有序区,然后将新的无序区调整为大根堆。
重复操作,无序区在递减,有序区在递增。
初始时,整个数组为无序区,第一次交换后无序区减一,有序区增一。
每一次交换,都是大根堆的堆顶元素插入有序区,所以有序区保持是有序的。

大根堆和小根堆
堆:是一颗完全二叉树。
大根堆:所有节点的子节点比其自身小的堆
小根堆:所有节点的子节点比其自身大的堆

堆与数组的关系

堆是一种逻辑结构(形象的表示数据的存储格式),数组则是数据的实际存储结构(对应数据的存储地址),堆中的根节点与左右子节点在存储数组中的位置关系如下:假设根节点在数组中的位置(数组下标)为 i ,那么左节点在数组中的位置(数组下标)为 i * 2 + 1 , 右节点在数组中的位置(数组下标)为 i * 2 + 2 。

 
 
以上是基本的知识点,具体代码如下所示:
        //堆排序算法(传递待排数组名,即:数组的地址。故形参数组的各种操作反应到实参数组上)
privatestaticvoid HeapSortFunction(int[] array)
{
try
{
BuildMaxHeap(array); //创建大顶推(初始状态看做:整体无序)
for (int i = array.Length -; i >; i--)
{
Swap(ref array[], ref array[i]); //将堆顶元素依次与无序区的最后一位交换(使堆顶元素进入有序区)
MaxHeapify(array, , i); //重新将无序区调整为大顶堆
}
}
catch (Exception ex)
{ }
} ///<summary>
/// 创建大顶推(根节点大于左右子节点)
///</summary>
///<param name="array">待排数组</param>
privatestaticvoid BuildMaxHeap(int[] array)
{
try
{
//根据大顶堆的性质可知:数组的前半段的元素为根节点,其余元素都为叶节点
for (int i = array.Length /-; i >=; i--) //从最底层的最后一个根节点开始进行大顶推的调整
{
MaxHeapify(array, i, array.Length); //调整大顶堆
}
}
catch (Exception ex)
{ }
} ///<summary>
/// 大顶推的调整过程
///</summary>
///<param name="array">待调整的数组</param>
///<param name="currentIndex">待调整元素在数组中的位置(即:根节点)</param>
///<param name="heapSize">堆中所有元素的个数</param>
privatestaticvoid MaxHeapify(int[] array, int currentIndex, int heapSize)
{
try
{
int left =* currentIndex +; //左子节点在数组中的位置
int right =* currentIndex +; //右子节点在数组中的位置
int large = currentIndex; //记录此根节点、左子节点、右子节点 三者中最大值的位置 if (left < heapSize && array[left] > array[large]) //与左子节点进行比较
{
large = left;
}
if (right < heapSize && array[right] > array[large]) //与右子节点进行比较
{
large = right;
}
if (currentIndex != large) //如果 currentIndex != large 则表明 large 发生变化(即:左右子节点中有大于根节点的情况)
{
Swap(ref array[currentIndex], ref array[large]); //将左右节点中的大者与根节点进行交换(即:实现局部大顶堆)
MaxHeapify(array, large, heapSize); //以上次调整动作的large位置(为此次调整的根节点位置),进行递归调整
}
}
catch (Exception ex)
{ }
} ///<summary>
/// 交换函数
///</summary>
///<param name="a">元素a</param>
///<param name="b">元素b</param>
privatestaticvoid Swap(refint a, refint b)
{
int temp =;
temp = a;
a = b;
b = temp;
}

堆排序算法(C#实现)的更多相关文章

  1. 堆排序算法 java 实现

    堆排序算法 java 实现 白话经典算法系列之七 堆与堆排序 Java排序算法(三):堆排序 算法概念 堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特 ...

  2. 必须知道的八大种排序算法【java实现】(三) 归并排序算法、堆排序算法详解

    一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...

  3. 【java排序】 归并排序算法、堆排序算法

    一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...

  4. Python3标准库:heapq堆排序算法

    1. heapq堆排序算法 堆(heap)是一个树形数据结构,其中子节点与父节点有一种有序关系.二叉堆(binary heap)可以使用一个有组织的列表或数组表示,其中元素N的子元素位于2*N+1和2 ...

  5. cb52a_c++_STL_堆排序算法make_push_pop_sort_heap

    cb52a_c++_STL_堆排序算法make_push_pop_sort_heapheapsort堆排序算法make_heap()-特殊的二叉树,每一个节点都比根小,根就是最大的数.大根堆,也可以做 ...

  6. Javascript中的冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序 算法性能分析

    阿里面试中有一道题是这样的: 请用JavaScript语言实现 sort 排序函数,要求:sort([5, 100, 6, 3, -12]) // 返回 [-12, 3, 5, 6, 100],如果你 ...

  7. Heapsort 堆排序算法详解(Java实现)

    Heapsort (堆排序)是最经典的排序算法之一,在google或者百度中搜一下可以搜到很多非常详细的解析.同样好的排序算法还有quicksort(快速排序)和merge sort(归并排序),选择 ...

  8. 堆排序算法的java实现

         堆积排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素.堆排序是不稳定的排序方法,辅助空间为O(1), 最坏时间复杂度为O ...

  9. 排序系列 之 堆排序算法 —— Java实现

       基本概念: 二叉堆是完全二叉树或者是近似完全二叉树. 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆. 当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆. 一般将二叉堆简称 ...

随机推荐

  1. HDU5669 Road 分层最短路+线段树建图

    分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) ​的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维 ...

  2. BZOJ2818: Gcd 欧拉函数求前缀和

    给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 如果两个数的x,y最大公约数是z,那么x/z,y/z一定是互质的 然后找到所有的素数,然后用欧拉函数求一 ...

  3. c pvr转存pvr.ccz格式

    pvr.ccz 是把pvr用zlib算法压缩后的图像格式,其优点是可以提升文件读取效率. 大多数情况下我们可以用一些工具来将pvr压缩到pvr.ccz ,下面提供一个c++方法来完成这个过程 int ...

  4. Flex 箭头(军标)库封装完成

    封装的一个月,在这个月期间还完成的一些其它的工作:公司有规定不能公布代码,我可以讲一下大致的流程,真的很抱歉! 1.用B样条曲线画箭头的两侧的曲线,这个要注意了,不要贝塞尔曲线,因为贝塞尔曲线的算法会 ...

  5. grep环境变量常用配置

    vim ~/.bashrc GREP_OPTIONS="-irns --exclude-dir=output --exclude=tags --exclude=*.files" 然 ...

  6. 动态链接库(DLL)的使用

    2013-07-04 http://blog.csdn.net/blpluto/article/details/5715182 感觉挺好,推荐去看看.

  7. ZOJ-2365 Strong Defence 贪心,BFS

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2365 我没看懂题目...这样理解:一个有向图,要给一些边染色,使 ...

  8. cloud-utils cloud-utils-growpart cloud-init

  9. Hadoop源码的编译过程详细解读(各版本)

    说在前面的话   重新试多几次.编译过程中会出现下载某个包的时间太久,这是由于连接网站的过程中会出现假死,按ctrl+c,重新运行编译命令. 如果出现缺少了某个文件的情况,则要先清理maven(使用命 ...

  10. FireFox浏览器的下载和安装、借助RamDisk让你的FireFox飞起来

    想说的是,为什么我要写此博文,算是纪念我对FireFox浏览器的一个入门.最近,开始接触了它,看到了很多IT牛人极力推荐使用 “ FireFox浏览器 ”作为开发. 深得大牛指导! 下载 安装 这是, ...