算法希尔排序&快速排序

希尔排序的一种缩小增量(Incremental)的排序,是直接插入排序的一种升级。

基本思想就是,将原有的数组arr,分成Incremental 个小数组,然后对各个小数组进行插入排序,当然我认为,也可以用其他排序算法。

然后将增量(Incremental)减半,再分组,再排序。

直到最后Incremental=1,也必须等于1,这时,就只能分成一组了,相当于对整个数组进行一次插入排序。

这样做的好处,在于,不断细分数组,使得在排序过程中减少了数据的移动量。

我的C#实现如下:

        /// <summary>
        
/// Shell sort O((nlogn)^2)
        
/// </summary>
        
/// <param name="arr"></param>
        public static void ShellSort(int[] arr)
        {
            if (arr == null)
            {
                throw new ArgumentNullException();
            }

            // Initializes the Incremental
            int inc = arr.Length / 2;
            while (inc > 0)
            {
                // Splits the array to arrays as many as number of Incremental.
                
// Members of index(i * inc + n) of the original array are in one splitted array.
                for (int n = 0; n < inc; n++)
                {
                    // Executes InsertSort logic in every splitted array,
                    
// Of course, this area can using other sort algorithms to implement, I think
                    for (int i = 1; i < arr.Length / inc; i++)
                    {
                        int j = i;
                        int temp = arr[j * inc + n];
                        while (j > 0 && temp < arr[(j - 1) * inc + n])
                        {
                            arr[j * inc + n] = arr[(j - 1) * inc + n];
                            j--;
                        }

                        arr[j * inc + n] = temp;
                    }
                }

                // subtract half of the Incremental till the Incremental equals 1
                inc = inc / 2;
            }
        }

这个算法的排序效率确实很高,据我测试怎么比QuickSort的还略快。

理论上快排的时间复杂度为O(nlogn),而希尔排序为O((nlogn)^2)。这就有点理论和实际的差距了吗。

快排的思想就是:

1)对整个数组(arr)取Left=0,Right=arr.Length-1

2)在(Left,Right)中取一个Key值(比如arr[Left]),也可以称作哨站,用两个index(i=Left,j=Right),i从左往右遍历,j从右往左遍历,找到两个值(arr[i]>=key,arr[j]<=key)

3)然后交换这两个值,知道i>=j结束一轮排序。

4)再递归取新的(Left=0,Right=i-1 )和(Left=i+1,Right=Right)两个分组进行2),3), 直到i-1<=Left 和 i+1>=Right, 结束

代码快排如下:

        /// <summary>
        
/// Quick sort, Expect time O(nlogn), bad case O(n^2)
        
/// </summary>
        
/// <param name="arr"></param>
        public static void QuickSort(int[] arr)
        {
            if (arr == null)
            {
                throw new ArgumentNullException();
            } 

            if (arr.Length > 1)
            {
                QuickSortRecursive(arr, 0, arr.Length - 1);
            }
        }

        private static void QuickSortRecursive(int[] arr, int left, int right)
        {
            // Assumption the left first value is the key value of the splitted array.
            int key = arr[left]; 
            int i = left;
            int j = right;
            do
            {
                // Find index of the array to make sure the data of the index not less than the key, from left to right.
                while (i < right && arr[i] < key)
                {
                    i++;
                }

                // Find index of the array to make sure the data of the index not greater than the key, from right to left.
                while (j > 0 && arr[j] > key)
                {
                    j--;
                }

                // if i less than j, than exchange values of the two indexes.
                if (i < j)
                {
                    // if the value of both indexes are equivalency,that means they equal to the value of key, so they not need be exchanged.
                    if (arr[i] == arr[j])
                    {
                        i++;
                        continue;
                    }

                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            } while (i < j);

            if (i - 1 > left)
            {
                // Sort left part of the array
                QuickSortRecursive(arr, left, i - 1);
            }
            if (j + 1 < right)
            {
                // Sort right part of the array
                QuickSortRecursive(arr, j + 1, right);
            }
        }
原文地址:https://www.cnblogs.com/ericwen/p/ShellSort_QuickSort.html