一天一算法之堆排序

我所知道的三种常用的复杂度为O(nlogn)的算法有三种,快速排序,堆排序,归并排序,今天说说堆排序。

首先说几个概念:

1.堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。 

2.大根堆:所有节点的子节点比其自身小的堆

     3.小根堆:所有节点的子节点比其自身大的堆 

     4.大根堆的堆顶元素就是这个堆中最大的元素。

直接上代码:

using System;
/// <summary>
/// 堆排序
/// 思路是改良简单选择排序每次寻找最小值的过程
/// 将前几次寻找的历史记录下来存在二叉树中
/// 从而减少了比较的次数,优化了性能
/// 复杂度为O(nlogn)
/// </summary>
namespace test
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			int [] arr = {3, 2, 7, 5, 4, 23, 54, 23, 65, 23, 65, 786, 21, 623, 75};
			HeapSort (arr);
			foreach (int i in arr) {
				Console.WriteLine (i);
			}
 		}
		//堆排序算法
		private static void HeapSort (int [] arr) {
			//先求出大根堆(及堆顶元素为最大,根节点从上到下越来越小的堆)
			//从而使无序数列变成一个有序堆
			for (int i = arr.Length / 2 - 1; i >= 0; i--) {
				HeapAdjust (arr, i, arr.Length);
			}
			//将堆顶元素与最后一个元素交换,求局部大根堆
			int temp;
			for (int i = arr.Length - 1; i > 0; i--) { 
				temp = arr [i];
				arr [i] = arr [0];
				arr [0] = temp;
				HeapAdjust (arr, 0, i);
			}
		}
		//求大根堆的方法
		private static void HeapAdjust (int [] arr, int index, int length) {
			int temp = arr [index];											//提前存下关键值
			for (int i = index * 2 + 1; i < length; i = i * 2 + 1) {		//遍历每层结点
				if (i < length - 1 && arr [i] < arr [i + 1]) {				//比较左孩子结点和右孩子结点,取大的索引位
					i++;
				}
				if (arr [index] >= arr [i]) {											//如果关键值本来就比孩子节点大直接跳出
					break;
				}
				arr [index] = arr [i];											//否则将关键值放在大的孩子结点位置
				index = i;
			}
			arr [index] = temp;												//将大的孩子结点值放在一开始传进的关键值位置
		}
	}
}


     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值