堆排序 C#實現


今天看堆排序,以前沒注意,寫個小程序記憶一下。

堆排序實際上就是個完全二叉樹,試着畫一棵試試,記憶算法很簡單,大根堆滿足跟比葉子大,小根堆反之。

算法思想見百度百科:

1,先將初始文件R[1..n]建成一個大根堆,此堆為初始的無序區

2,再將關鍵字最大的記錄R[1](即堆頂)和無序區的最后一個記錄R[n]交換,由此得到新的無序區R[1..n-1]和有序區R[n],且滿足R[1..n-1].keys≤R[n].key
3,由於交換后新的根R[1]可能違反堆性質,故應將當前無序區R[1..n-1]調整為堆。然后再次將 R[1..n-1]中關鍵字最大的記錄R[1]和該區間的最后一個記錄R[n-1]交換,由此得到新的無序區R[1..n-2]和有序區R[n- 1..n],且仍滿足關系R[1..n-2].keys≤R[n-1..n].keys,同樣要將R[1..n-2]調整為堆。

拿數組 int[] lst = new int[6] { 4, 9, 5, 1, 7, 3};舉例說明

(1) 第一次找到最大根 lst[1] = 9,跟lst[5]交換,結果-> { 4, 3, 5, 1, 7,9} ,無序區為{ 4, 3, 5, 1, 7} ,有序區為{9}

(2) 第二次找到 無序區為{ 4, 3, 5, 1, 7}最大根lst[4]=7跟自己交換,結果-> { 4, 3, 5, 1, 7,9} ,無序區為{ 4, 3, 5, 1} ,有序區為{7,9}

(3) 第三次找到 無序區為{ 4, 3, 5, 1}最大根lst[2]=5跟lst[3]=1交換,結果-> { 4, 3, 1, 5, 7,9} ,無序區為{ 4, 3, 1} ,有序區為{5,7,9}

(3) 第四次找到 無序區為{ 4, 3, 1}最大根lst[0]=4跟lst[2]=1交換,結果-> { 1, 3, 4, 5, 7,9} ,無序區為{ 1, 3} ,有序區為{4,5,7,9}

...

時間復雜度O(nlogn)

 

代碼如下:

 

 static void Main(string[] args)
        {
            try
            {
                int[] lst = new int[6] { 4, 9, 5, 1, 7, 3};

                foreach (var item in lst)
                {
                    Console.WriteLine(item + ", ");
                }
                Console.WriteLine("---------------------------");

                int maxid = GetMax(lst.Length, lst);
                HeapSort(maxid, lst);

                foreach (var item in lst)
                {
                    Console.WriteLine(item + ", ");
                }

                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey();
        }

        /// <summary>
        /// 交換
        /// </summary>
        /// <param name="maxIdx">無序區最大值Idx</param>
        /// <param name="idx">有序區目標位置</param>
        /// <param name="lst">序列</param>
        public static void Swap(int maxIdx, int idx, int[] lst)
        {
            int midx = maxIdx;
            int temp = lst[idx];
            lst[idx] = lst[maxIdx];
            lst[maxIdx] = temp;
        }

        /// <summary>
        /// 獲取無序區最大值
        /// </summary>
        /// <param name="maxLen">無序區最大長度</param>
        /// <param name="lst">序列</param>
        public static int GetMax(int maxLen, int[] lst)
        {
            int maxIdx = 0;
            for (var i = 0; i < maxLen; i++)
            {
                if (lst[i] > lst[maxIdx])
                    maxIdx = i;  
            }

            return maxIdx;
        }

        /// <summary>
        /// 堆排序
        /// </summary>
        /// <param name="maxIdx">無序區最大值位置</param>
        /// <param name="lst">序列</param>
        /// <returns>序列</returns>
        public static IList<int> HeapSort(int maxIdx, int[] lst)
        {
            int i = lst.Length - 1;
            int k = 0;

            while (i > -1)
            {
                Swap(maxIdx, i, lst);
                k++;
                //每次縮短無序區最大位置
                maxIdx = GetMax(lst.Length - k, lst);
                i--;
            }

            return lst;
        }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM