C#資料結構與演算法系列(二十一):希爾排序演算法(ShellSort)

IT技術派發表於2020-07-04

1.介紹

希爾排序是希爾(Donald Shell)於1959年提出的一種排序演算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的一個更高效的版本,也稱為縮小增量排序。

2.基本思想

希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止

3.示意圖

 

 4.程式碼

using System;

namespace DataStructure
{
    public class ShellSort
    {
        /// <summary>
        /// 測試希爾排序
        /// </summary>
        public static void Test()
        {
            int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };

            Console.WriteLine("需要排序的陣列:" + ArrayToString(arr));

            Console.WriteLine("\n封裝後的測試");

            //測試封裝後的希爾排序
            Sort(arr);

            Console.WriteLine("\n封裝前的測試");


            arr = new int[] { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };

            int temp = 0;
            //希爾排序第一輪
            //因為第一輪排序,是將十個資料分成了五組
            for (int i = 5; i < arr.Length; i++)
            {
                //遍歷各組中所有元素(10/2=5)步長五
                for (int j = i - 5; j >= 0; j -= 5)
                {
                    if (arr[j] > arr[j + 5])
                    {
                        temp = arr[j];

                        arr[j] = arr[j + 5];

                        arr[j + 5] = temp;
                    }
                }
            }

            Console.WriteLine("\n第一輪希爾排序的結果:" + ArrayToString(arr)); //3,5,1,6,0,8,9,4,7,2

            //希爾排序第二輪
            //因為第二輪排序,是將十個資料分成了5/2=2組
            for (int i = 2; i < arr.Length; i++)
            {
                for (int j = i - 2; j >= 0; j -= 2)
                {
                    if (arr[j] > arr[j + 2])
                    {
                        temp = arr[j];

                        arr[j] = arr[j + 2];

                        arr[j + 2] = temp;
                    }
                }
            }

            Console.WriteLine("\n第二輪希爾排序的結果:" + ArrayToString(arr));

            //希爾排序第三輪
            //因為第三輪排序,是將十個資料分成了2/2=1組
            for (int i = 1; i < arr.Length; i++)
            {
                for (int j = i - 1; j >= 0; j -= 1)
                {
                    if (arr[j] > arr[j + 1])
                    {
                        temp = arr[j];

                        arr[j] = arr[j + 1];

                        arr[j + 1] = temp;
                    }
                }
            }

            Console.WriteLine("\n第三輪希爾排序的結果:" + ArrayToString(arr));
        }

        /// <summary>
        /// 封裝希爾排序
        /// </summary>
        /// <param name="arr"></param>
        private static void Sort(int[] arr)
        {
            int temp = 0;

            int count = 0;
            //遍歷各組中的所有元素(共gap組,每組有個元素),步長gap
            for (int gap = arr.Length / 2; gap > 0; gap /= 2)
            {
                for (int i = gap; i < arr.Length; i++)
                {
                    for (int j = i - gap; j >= 0; j -= gap)
                    {
                        //如果當前元素大於加上步長後的那個元素,說明交換
                        if (arr[j] > arr[j + gap])
                        {
                            temp = arr[j];

                            arr[j] = arr[j + gap];

                            arr[j + gap] = temp;
                        }
                    }
                }

                Console.WriteLine($"\n第{++count }輪希爾排序的結果:{ArrayToString(arr)}");
            }
        }

        private static string ArrayToString(int[] arr)
        {
            return string.Join(",", arr);
        }
    }
}

5.演示結果

 

相關文章