ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

重新整理数据结构与算法(c#)—— 堆排序[二十一]

2020-07-10 11:01:35  阅读:232  来源: 互联网

标签:arr temp c# lenght 堆排序 重新整理 int 节点


前言

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

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;
}

测试的时间为:

标签:arr,temp,c#,lenght,堆排序,重新整理,int,节点
来源: https://www.cnblogs.com/aoximin/p/13260098.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有