原来一直用快排来着,觉得堆排太麻烦。。。
但是上大学之后发现脸一直不怎么样,倒霉事无论多小的概率都能被我碰上,所以就去学堆排了,因为就算是二分的快排还是有可能造成退化的现象,所以还是稳定在NlogN的堆排省心。。。
因为用的二叉树的性质做的,所以数组的下标从一开始,而不是零。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HeapSort
{
class Program
{
static void Main(string[] args)
{
int[] num = { 9, 8, 7, 6, 5, 100, 3, 2, 1, 0 };
HeapSort hsort = new HeapSort(num);
hsort.GetResult(out num);
foreach (int j in num)
Console.WriteLine(j);
}
}
class HeapSort
{
private int[] Num;
private int ArrayLenth;
public HeapSort(int[] num)
{
Num = new int[num.Length + 1];
ArrayLenth = num.Length;
for (int i = 1; i < ArrayLenth; i++)//为了利用二叉树的性质 既父节点下标乘二或者乘二加一为其孩子节点
this.Num[i] = num[i - 1];
}
private void HSort()
{
int i, l, k;
l = ArrayLenth;
while (l > 1)
{
if (l == ArrayLenth) i = l / 2;//如果已经建完一次大根堆,那么就只有根节点的位置不对喽
else i = 1;
while (i > 0)
{
k = i;
while (k <= l / 2 && k > 0)//保证当前节点不是叶子节点
{
if (l >= k * 2 + 1)//如果有右孩子
{
if (Num[k] < Num[k * 2] || Num[k] < Num[k * 2 + 1])//父节点比孩子节点小,说明要改变位置
{
if (Num[k * 2] > Num[k * 2 + 1])//如果左孩子比右孩子大,那么把左孩子提到根节点
{
Num[0] = Num[k * 2];
Num[k * 2] = Num[k];
Num[k] = Num[0];
k = k * 2;//继续调整
}
else
{
Num[0] = Num[k * 2 + 1];
Num[k * 2 + 1] = Num[k];
Num[k] = Num[0];
k = k * 2 + 1;
}
}
else break;//如果父亲节点比孩子节点都大说明不用调整
}
else//如果没有右孩子
{
if (Num[k] < Num[k * 2])
{
Num[0] = Num[k * 2];
Num[k * 2] = Num[k];
Num[k] = Num[0];
k = k * 2;
}
break;//如果没有右孩子说明已经到了最后一个有孩子的节点
}
}
i--;//调整数组中上一个节点
}
Num[0] = Num[1];//将根节点放到最后一个,也就是最大的节点
Num[1] = Num[l];
Num[l] = Num[0];
l--;//下一次不用再排刚才找到的节点 因为刚才找到的最大的节点的位置始终都在Num[l]
}
}
public void GetResult(out int[] num)
{
num = new int[ArrayLenth];
HSort();
for (int i = 1; i <= ArrayLenth; i++)
{
num[i - 1] = Num[i];
}
}
}
}