堆排序算法(C#实现)
在软件设计相关领域,“堆(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#实现)的更多相关文章
- 堆排序算法 java 实现
堆排序算法 java 实现 白话经典算法系列之七 堆与堆排序 Java排序算法(三):堆排序 算法概念 堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特 ...
- 必须知道的八大种排序算法【java实现】(三) 归并排序算法、堆排序算法详解
一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...
- 【java排序】 归并排序算法、堆排序算法
一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...
- Python3标准库:heapq堆排序算法
1. heapq堆排序算法 堆(heap)是一个树形数据结构,其中子节点与父节点有一种有序关系.二叉堆(binary heap)可以使用一个有组织的列表或数组表示,其中元素N的子元素位于2*N+1和2 ...
- cb52a_c++_STL_堆排序算法make_push_pop_sort_heap
cb52a_c++_STL_堆排序算法make_push_pop_sort_heapheapsort堆排序算法make_heap()-特殊的二叉树,每一个节点都比根小,根就是最大的数.大根堆,也可以做 ...
- Javascript中的冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序 算法性能分析
阿里面试中有一道题是这样的: 请用JavaScript语言实现 sort 排序函数,要求:sort([5, 100, 6, 3, -12]) // 返回 [-12, 3, 5, 6, 100],如果你 ...
- Heapsort 堆排序算法详解(Java实现)
Heapsort (堆排序)是最经典的排序算法之一,在google或者百度中搜一下可以搜到很多非常详细的解析.同样好的排序算法还有quicksort(快速排序)和merge sort(归并排序),选择 ...
- 堆排序算法的java实现
堆积排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素.堆排序是不稳定的排序方法,辅助空间为O(1), 最坏时间复杂度为O ...
- 排序系列 之 堆排序算法 —— Java实现
基本概念: 二叉堆是完全二叉树或者是近似完全二叉树. 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆. 当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆. 一般将二叉堆简称 ...
随机推荐
- Codeforces 14D
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const i ...
- [Raobin] Ext.net 页面由于CMB的store和对图像同时执行,所以不会触发非空验证 所以会在后台直接调Js去验证
X.Call("valid", vm.ID_EDIT_FORM); x.Call("前台的js的方法名称"," 参数为集合");
- nmon for linux
nmon(为Nigel's performance Monitor的简写) for linux工具是 IBM开源的在POWER, x86, x86_64, Mainframe & now AR ...
- Ruby require 路径问题
require 负责引用一个外部文件,可以省略".rb"字样. 如: require 'foo.bar' 等价于 require 'foo' 在Ruby中,同一目录下的文件, 如 ...
- 安装solr
安装之前先关闭防火墙.安装好jdk和tomcat 1.启动tomcat的命令为:apache-tomcat-7.0.61/bin/startup.sh 2.拷贝solr目录下example/webap ...
- Java笔记(二十三)……Map集合
Map接口 Map<K,V> 该集合存储的是键值对,成对往集合里存,而且要保证键的唯一性 常用方法 添加 Vput(K key, V value) voidputAll(Map<? ...
- SqlServer定时跑一段SQL语句
1.请把这段SQL语句写成一个存储过程,然后需要在B上面开启 SQL Server Agent服务,如下图: 2.开启完之后,打开数据库管理工具,然后依下图所示,展开“SQL Server Agent ...
- mongdb高级操作(group by )
首先介绍哈方法 /** * 利用java驱动自带函数分组查询 * @param key 用来分组文档的字段 [group by key] * @param cond 执行过滤的条件 [where na ...
- Cocos2d-x学习笔记之Cocos2d-x开发环境搭建
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Cocos2d-x源码包下载地址: http://cocos2d-x.org/projects/cocos2d-x/ ...
- 部署服务--NLB
通过服务部署NLB,是对某一层(一层下面可以自定义VM实例数量)服务下的多台VM进行NLB,而不是对多个层进行NLB.需要先进行如下准备: 1.VM需要使用静态IP和静态MAC,所以需要先在进行NLB ...