原來一直用快排來着,覺得堆排太麻煩。。。
但是上大學之後發現臉一直不怎麼樣,倒黴事無論多小的概率都能被我碰上,所以就去學堆排了,因爲就算是二分的快排還是有可能造成退化的現象,所以還是穩定在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];
}
}
}
}