好用的排序之堆排序

原來一直用快排來着,覺得堆排太麻煩。。。

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


發佈了28 篇原創文章 · 獲贊 8 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章