前言

将下面按照从小到大排序:

int[] arr = { 4, 6, 8, 5, 9 };

这时候可以通过冒泡排序,计数排序等。

但是一但数据arr很大,那么会产生排序过于缓慢,堆排序就是一个很好的解决方案。

树的堆,有最大堆和最小堆。

看下最大堆:

它是这样子的,就是说一个节点的大小一定大于它的左节点和右节点大小。

如何利用最大堆。进行从大到小的排序呢?

细节

细节如下:

假如堆排序后:

那么用root(根节点,最大节点)和最后一个数组元素进行交换,那么下次进行堆排序的元素就是length-1个,就不用管最后一个元素,因为最后一个元素已经排好序,且最大。

那么现在回到一个问题上了,就是如何进行最大堆排序呢?

有如下步骤:

1.找到树的最后非叶子节点。arr.length/2-1



现在只需要关注红框的子树。

2.先把最后一个非叶子节点作为子树,进行堆排序。(比较他们的左右节点,把最大的和根节点进行交换)

那么也就是下面已经是最大堆了。

然后在往上比较:

分为两种情况,一个就是加入有节点和根节点进行交换的话,那个节点就要作为子树进行堆排序。

比如这里,4和9要进行交换了,那么下面就不是最大堆了,所以左子树要再次进行最大堆结构化。

代码

static void Main(string[] args)
{
int[] arr = { 4, 6, 8, 5, 9 };
//制作成第一个大顶堆
for (int i=arr.Length/2-1;i>=0;i--)
{
adjustHeap(arr,i,arr.Length);
}
int temp = 0;
for (int j = arr.Length - 1; j > 0; j--)
{
//交换
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
// j 为需要比较元素的个数为:j-1+1=j
adjustHeap(arr, 0, j);
}
foreach (var i in arr)
{
Console.WriteLine(i);
}
Console.ReadKey();
} public static void adjustHeap(int[] arr,int i,int lenght)
{
int temp = arr[i]; for (int k= 2*i+1;k < lenght; k=2*k+1)
{
if (k + 1 < lenght)
{
if (arr[k] < arr[k + 1])
{
k++;
}
}
if (arr[k] > arr[i])
{
arr[i] = arr[k];
i = k;
}
else
{
//因为下面都是排序好了的
break;
}
}
arr[i] = temp;
}

结果:

性能测试

static void Main(string[] args)
{
//int[] arr = { 4, 6, 8, 5, 9 }; int[] arr = new int[8000000];
for (int i = 0; i < 8000000; i++)
{
arr[i] = (int)((new Random().Next()) * 8000000); // 生成一个[0, 8000000) 数
}
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//制作成第一个大顶堆
for (int i=arr.Length/2-1;i>=0;i--)
{
adjustHeap(arr,i,arr.Length);
}
int temp = 0;
for (int j = arr.Length - 1; j > 0; j--)
{
//交换
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
// j 为需要比较元素的个数为:j-1+1=j
adjustHeap(arr, 0, j);
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds); Console.ReadKey();
} public static void adjustHeap(int[] arr,int i,int lenght)
{
int temp = arr[i]; for (int k= 2*i+1;k < lenght; k=2*k+1)
{
if (k + 1 < lenght)
{
if (arr[k] < arr[k + 1])
{
k++;
}
}
if (arr[k] > arr[i])
{
arr[i] = arr[k];
i = k;
}
else
{
//因为下面都是排序好了的
break;
}
}
arr[i] = temp;
}

测试的时间为:

重新整理数据结构与算法(c#)—— 堆排序[二十一]的更多相关文章

  1. C#数据结构与算法系列(二十一):希尔排序算法(ShellSort)

    1.介绍 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法.希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序. 2.基本思想 希尔排 ...

  2. Java数据结构与算法解析(十二)——散列表

    散列表概述 散列表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 散列表的思路很简单,如果所有的键都是整数,那么就可以使用一个简单 ...

  3. 数据结构与算法16—平衡二叉(AVL)树

    我们知道,对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度O(log2n)同时也由此而决定.但是,在某些极端的情况下(如在 ...

  4. C#数据结构与算法系列(二十三):归并排序算法(MergeSort)

    1.介绍 归并排序(MergeSort)是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分(divide)成一些小的问题然后递归求解, 而治(conquer)的阶段则将分的阶段得 ...

  5. Java数据结构和算法(十二)——2-3-4树

    通过前面的介绍,我们知道在二叉树中,每个节点只有一个数据项,最多有两个子节点.如果允许每个节点可以有更多的数据项和更多的子节点,就是多叉树.本篇博客我们将介绍的——2-3-4树,它是一种多叉树,它的每 ...

  6. 数据结构与算法问题 AVL二叉平衡树

    AVL树是带有平衡条件的二叉查找树. 这个平衡条件必须保持,并且它必须保证树的深度是O(logN). 一棵AVL树是其每一个节点的左子树和右子树的高度最多差1的二叉查找树. (空树的高度定义为-1). ...

  7. C#数据结构与算法系列(二十):插入排序算法(InsertSort)

    1.介绍 插入排序算法属于内部排序算法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的 2.思想 插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看 ...

  8. 重新整理数据结构与算法(c#)—— 图的深度遍历和广度遍历[十一]

    参考网址:https://www.cnblogs.com/aoximin/p/13162635.html 前言 简介图: 在数据的逻辑结构D=(KR)中,如果K中结点对于关系R的前趋和后继的个数不加限 ...

  9. C#数据结构与算法系列(二):稀疏数组(SparseArray)

    1.介绍 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组.    稀疏数组的处理方法是: 1.记录数组一共有几行几列,有多少个不同的值    2.把具有不同值的元素的 ...

  10. C#数据结构与算法系列(二十二):快速排序算法(QuickSort)

    1.介绍 快速排序(QuickSort)是对冒泡排序的一种改进,基本思想是:通过一趟排序将要排序的数据分割成独立的两部分, 其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数 ...

随机推荐

  1. .npmrc 项目的 默认安装配置

    .npmrc registry=http://192.168.77.105:8081/nexus/content/groups/npm-all/

  2. iVCam 可以当电脑的摄像头 同一个wifi

    iVCam 可以当电脑的摄像头 同一个wifi

  3. PRD(产品需求文档)与SRS(软件需求规格说明书)的区别

    需求分析是软件开发过程中很重要的一个环节,目前需求分析完成后输出的文档有2种体系,一个是SRS(Software Requirements Specification,软件需求规格说明书),一个是PR ...

  4. [原创] KCP 源码分析(上)

    KCP 协议是一种可靠的传输协议,对比 TCP 取消了累计确认(延迟 ACK).减小 RTO增长速度.选择性重传而非全部重传.通过用流量换取低时延. KCP 中最重要的两个数据结构IKCPCB和IKC ...

  5. Lambda Web Browser使用教程

    Lambda web browser是一个功能强大的UE内置浏览器插件, 允许用户在编辑器模式和运行时启动一个浏览器窗口, 对于一些采用传统BS架构的项目而言, 控制页面都放在前段, 若想要将控制页面 ...

  6. 5G时代,3DCAT助力AR/VR内容上云

    一.5G网络三大应用场景 目前中国的5G技术正在加速发展,5G网络拥有增强型移动宽带.超高可靠低时延通信.海量机器类通信三大技术特点和应用场景.其中增强型移动宽带技术特点与AR&VR行业相关, ...

  7. tableau 工作表分页

    原创优阅达数据科技有限公司 https://mp.weixin.qq.com/s?__biz=MzA5MTU3NDI2NQ==&mid=2649465570&idx=1&sn= ...

  8. RepVGG:VGG,永远的神! | CVPR 2021

    RepVGG将训练推理网络结构进行独立设计,在训练时使用高精度的多分支网络学习权值,在推理时使用低延迟的单分支网络,然后通过结构重参数化将多分支网络的权值转移到单分支网络.RepVGG性能达到了SOT ...

  9. KingbaseES V8R6 fillfactor 对于表的影响

    前言 fillfactor 表的填充因子是一个介于 10 和 100 之间的百分数.100是默认值.如果指定了较小的填充因子,INSERT操作仅按照填充因子指定的百分率填充表页.每个页上的剩余空间将用 ...

  10. KingbaseES 配置root.sh实现数据库服务开机自启动

    案例说明: KingbaseES数据库在部署完成后,支持数据库服务开机自启动,部署完成后,root用户(Linux)执行安装软件目录下的root.sh脚本后,可以实现数据库服务开机自启动. 适用版本: ...