【前言】刚开始小编对堆排序可是一头雾水,通过这几天的学习和整理,最重要的是亲手实践了堆排序的过程以及代码实现,豁然开朗了,赶紧把学习过程总结下来,分享给大家。排序算法之堆排序开课啦!
一、什么是堆排序
堆排序是对选择排序的一种优化,可以利用数组的特点快速定位指定索引的元素。
堆的定义:若有一个关键字序列满足{k1,k2,…,kn}满足ki<=k2i ki<=k2i+1(或ki>=k2i ki>=k2i+1),其中,i=1,2,…,n/2,则称这个n个键值的序列{k1,k2,…,kn}为最小堆(或最大堆)。
二、堆排序的过程(以大根堆为例)
1)构建初始堆(最大堆)
2)输出堆顶元素,用最后一个数代替
3)再次调整为最大堆
4)重复上面步骤
图形解释:
1)给出一个数组array[]={16,7,3,20,17,8},将该数组构建成一个完全二叉树如下图
2)构建初始堆(最大堆),从最后一个非叶节点也就是3开始调整:
(下图是用根节点先和右孩子节点比,然后再和左孩子节点比,我们也可以先比较左孩子和右孩子,选出较大的孩子和父节点比较,这样交换一次就可以了)
20和16交换之后不满足堆的定义,这是需要再次调整将16和17交换位置,这样就得到了初始堆
3)这时输出堆顶元素20,将3放到堆顶再次调整为最大堆
这样就完成了堆排序的过程,我们一定要亲自画一下这个过程,这样我们才能对排序的过程有更加清晰的认识。
三、代码实现
static void Main(string[] args)
{
int[] arr = { 16, 7, 3, 20, 17, 8 };
Console.WriteLine("排序前的数组:");
foreach (int item in arr)
{
Console.Write(item + " ");
}
Console.WriteLine();
Console.WriteLine("排序后的数组:");
//调用堆排序
HeapSort(arr, arr.Length -1);
foreach (int item in arr)
{
Console.Write(item + " ");
}
Console.WriteLine();
Console.Read();
}
/// <summary>
/// 构建堆
/// </summary>
static void HeapAdjust(int[] arr,int parent,int length)
{
int temp = arr[parent];
int child = 2 * parent + 1;
while (child <length )
{
if (child +1<length && arr[child]<arr[child+1])
{
child++;
}
if (temp>=arr[child])
{
break;
}
arr[parent] = arr[child];
parent = child;
child = 2 * parent + 1;
}
arr[parent] = temp;
foreach (int item in arr)
{
Console.Write(item + " ");
}
Console.WriteLine();
}
public static void HeapSort(int[] arr, int length)
{
for (int i= arr.Length/2-1; i>=0 ; i--)
{
HeapAdjust(arr, i, arr.Length);
}
for (int i = arr.Length - 1; i > 0; --i)
{
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
HeapAdjust(arr, 0, i);
}
}
【总结】只要我们用心去分析,亲手去实践,所有的问题都不在话下。实在不明白的地方我们也可以和别人交流一下,大家赶快动手去实践吧!