重新整理数据结构与算法(c#)—— 堆排序[二十一]
前言
将下面按照从小到大排序:
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#)—— 堆排序[二十一]的更多相关文章
- C#数据结构与算法系列(二十一):希尔排序算法(ShellSort)
1.介绍 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法.希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序. 2.基本思想 希尔排 ...
- Java数据结构与算法解析(十二)——散列表
散列表概述 散列表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 散列表的思路很简单,如果所有的键都是整数,那么就可以使用一个简单 ...
- 数据结构与算法16—平衡二叉(AVL)树
我们知道,对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度O(log2n)同时也由此而决定.但是,在某些极端的情况下(如在 ...
- C#数据结构与算法系列(二十三):归并排序算法(MergeSort)
1.介绍 归并排序(MergeSort)是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分(divide)成一些小的问题然后递归求解, 而治(conquer)的阶段则将分的阶段得 ...
- Java数据结构和算法(十二)——2-3-4树
通过前面的介绍,我们知道在二叉树中,每个节点只有一个数据项,最多有两个子节点.如果允许每个节点可以有更多的数据项和更多的子节点,就是多叉树.本篇博客我们将介绍的——2-3-4树,它是一种多叉树,它的每 ...
- 数据结构与算法问题 AVL二叉平衡树
AVL树是带有平衡条件的二叉查找树. 这个平衡条件必须保持,并且它必须保证树的深度是O(logN). 一棵AVL树是其每一个节点的左子树和右子树的高度最多差1的二叉查找树. (空树的高度定义为-1). ...
- C#数据结构与算法系列(二十):插入排序算法(InsertSort)
1.介绍 插入排序算法属于内部排序算法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的 2.思想 插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看 ...
- 重新整理数据结构与算法(c#)—— 图的深度遍历和广度遍历[十一]
参考网址:https://www.cnblogs.com/aoximin/p/13162635.html 前言 简介图: 在数据的逻辑结构D=(KR)中,如果K中结点对于关系R的前趋和后继的个数不加限 ...
- C#数据结构与算法系列(二):稀疏数组(SparseArray)
1.介绍 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 稀疏数组的处理方法是: 1.记录数组一共有几行几列,有多少个不同的值 2.把具有不同值的元素的 ...
- C#数据结构与算法系列(二十二):快速排序算法(QuickSort)
1.介绍 快速排序(QuickSort)是对冒泡排序的一种改进,基本思想是:通过一趟排序将要排序的数据分割成独立的两部分, 其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数 ...
随机推荐
- DOSBox0.74使用Debug时p命令报错
环境 操作系统:Windows 10 DOSBox 0.74 DEBUG.EXE 从 Windows XP 或其他复制到的DOSBox下 问题 在学习到 王爽的<汇编语言>时,第 4章,第 ...
- 如何下载RTMP/http直播源直播视频(比尔下载器使用完整教程)
之前已经介绍了如何抓取各种app直播源及在线视频地址,本节内容将详细介绍如何下载rtmp/http直播源的直播视频,请注意,rtmp/http指协议,不针对任何app,凡是使用了以上协议的基本原理一样 ...
- 适用于AbpBoilerplate的RocketChat Api库
RocketChat 适用于AbpBoilerplate的RocketChat Api库 Rocket.Chat 是一个免费.开源.可扩展.高度可定制且安全的平台,可让您与团队进行交流和协作.共享文件 ...
- C#移除List中特定元素
在List里面移除其中一个元素之后,原有的索引以及索引对应的值会发生改变,如果按照原有的索引值删除,就会误删除其它元素. 1.实现思路 原始List为A,将需要删除的元素放到一个List B里面,遍历 ...
- getUserMedia 获取 摄像头 拍照 代码 1920-1080 video canvas
getUserMedia 获取 摄像头 拍照 代码 1920-1080 video canvas 20210422 摄像头代码 是基于 https 协议的,需要开启协议后才能测试 http-serve ...
- Android TextView设置某段文字可点击
初次进入app,需要有个勾选隐私协议的UI,其中的隐私协议文字点击是可跳转到新页面对隐私协议机型展示 这里选择使用Android自带的SpannedString来设置TextView的文字内容即可设置 ...
- day01-1-需求分析和项目设计
满汉楼01 1.需求分析 满汉楼项目说明 因为javaGUI不是学习的重点,这里将继续使用控制台界面来代替界面和事件处理 完成的功能: 登录 订座 点餐 结账 查看账单等功能 在实际项目中,独立完成项 ...
- DWR之入门实例(一)
DWR(Direct Web Remoting)是一个WEB远程调用框架.利用这个框架可以让AJAX开发变得很简单.利用DWR可以在客户端利用JavaScript直接调用服务端的Java方法并返回值给 ...
- verilog勘误系列之-->设计行为仿真和时序仿真不一致分析
描述 最近在vivado中设计一个计算器: 28bit有符号加减法,结果出现行为仿真和时序仿真不一致情况 原因 本篇是由于组合逻辑部分敏感信号使用错误导致 代码 r_a, r_b : 对计算数据a, ...
- 一种OSD 简单实现 (文字反色---opencv、字体切换---freetype2(中文、空格))
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...