堆排序算法(C#实现)
来源:互联网 发布:网络疯传婚礼新娘吃 编辑:程序博客网 时间:2024/05/19 20:39
在软件设计相关领域,“堆(Heap)”的概念主要涉及到两个方面:
一种是数据结构,逻辑上是一颗完全二叉树,存储上是一个数组对象(二叉堆)。
另一种是垃圾收集存储区,是软件系统可以编程的内存区域。
本文所说的堆指的是前者,另外,这篇文章中堆中元素的值均以整形为例
堆排序的时间复杂度是O(nlog2n),与快速排序达到相同的时间复杂度. 但是在实际应用中,我们往往采用快速排序而不是堆排序. 这是因为快速排序的一个好的实现,往往比堆排序具有更好的表现. 堆排序的主要用途,是在形成和处理优先级队列方面. 另外, 如果计算要求是类优先级队列(比如, 只要返回最大或者最小元素, 只有有限的插入要求等), 堆同样是很适合的数据结构.
堆排序
堆排序是一种选择排序。是不稳定的排序方法。时间复杂度为O(nlog2n)。
堆排序的特点是:在排序过程中,将排序数组看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录。
基本思想
1.将要排序的数组创建为一个大根堆。大根堆的堆顶元素就是这个堆中最大的元素。
2.将大根堆的堆顶元素和无序区最后一个元素交换,并将无序区最后一个位置例入有序区,然后将新的无序区调整为大根堆。
重复操作,无序区在递减,有序区在递增。
初始时,整个数组为无序区,第一次交换后无序区减一,有序区增一。
每一次交换,都是大根堆的堆顶元素插入有序区,所以有序区保持是有序的。
大根堆和小根堆
堆:是一颗完全二叉树。
大根堆:所有节点的子节点比其自身小的堆
小根堆:所有节点的子节点比其自身大的堆
堆与数组的关系
堆是一种逻辑结构(形象的表示数据的存储格式),数组则是数据的实际存储结构(对应数据的存储地址),堆中的根节点与左右子节点在存储数组中的位置关系如下:假设根节点在数组中的位置(数组下标)为 i ,那么左节点在数组中的位置(数组下标)为 i * 2 + 1 , 右节点在数组中的位置(数组下标)为 i * 2 + 2 。
//堆排序算法(传递待排数组名,即:数组的地址。故形参数组的各种操作反应到实参数组上) private static void HeapSortFunction(int[] array) { try { BuildMaxHeap(array); //创建大顶推(初始状态看做:整体无序) for (int i = array.Length - 1; i > 0; i--) { Swap(ref array[0], ref array[i]); //将堆顶元素依次与无序区的最后一位交换(使堆顶元素进入有序区) MaxHeapify(array, 0, i); //重新将无序区调整为大顶堆 } } catch (Exception ex) { } } /// <summary> /// 创建大顶推(根节点大于左右子节点) /// </summary> /// <param name="array">待排数组</param> private static void BuildMaxHeap(int[] array) { try { //根据大顶堆的性质可知:数组的前半段的元素为根节点,其余元素都为叶节点 for (int i = array.Length / 2 - 1; i >= 0; i--) //从最底层的最后一个根节点开始进行大顶推的调整 { MaxHeapify(array, i, array.Length); //调整大顶堆 } } catch (Exception ex) { } } /// <summary> /// 大顶推的调整过程 /// </summary> /// <param name="array">待调整的数组</param> /// <param name="currentIndex">待调整元素在数组中的位置(即:根节点)</param> /// <param name="heapSize">堆中所有元素的个数</param> private static void MaxHeapify(int[] array, int currentIndex, int heapSize) { try { int left = 2 * currentIndex + 1; //左子节点在数组中的位置 int right = 2 * currentIndex + 2; //右子节点在数组中的位置 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> private static void Swap(ref int a, ref int b) { int temp = 0; temp = a; a = b; b = temp; }
- 堆排序算法(C#实现)
- C# 实现常用的算法-- 堆排序(转)
- 排序算法(C实现)--------- 堆排序
- 堆排序C#实现
- C#实现堆排序
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现
- 堆排序算法实现(C++)
- 堆排序算法(java实现)
- 堆排序算法(C & Java 实现)
- 堆排序算法(c 语言实现)
- Android adb push 操作时问题的解决方法及ubuntu下avd的生成
- 结构体对齐详解
- 从无序数组中获取最小的M个元素(小顶堆实现)
- Charting Basics制作图表的基本知识
- SRM 588 D2 L3:GameInDarknessDiv2,DFS
- 堆排序算法(C#实现)
- 外包与非外包 浅谈
- Eclipse+Java+OpenCV246人脸检测
- 插入排序算法--直接插入算法,折半排序算法,希尔排序算法(C#实现)
- HDU-1256
- 2013/08/16 C# WPF 学习笔记
- java
- Warm up(hdu4612双连通分量+缩点+树的直径)
- zoj 3165 (最小割,最大点权独立集)