zoukankan      html  css  js  c++  java
  • 算法希尔排序&快速排序

    希尔排序的一种缩小增量(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);
                }
            }
  • 相关阅读:
    Spring之IOC、AOP和事务
    Spring Aware接口
    ReentrantLock原理
    基于AnnotationConfigApplicationContext的容器创建过程(Spring Version 5.2.0)
    基于AnnotationConfigApplicationContext的Bean加载过程(Spring Version 5.2.0)
    Future和CompletableFuture
    ThreadLocal原理
    Oracle 11g R2 数据库卸载教程
    Oracle 11g R2 数据库安装教程
    SQL Server 2017数据库卸载教程
  • 原文地址:https://www.cnblogs.com/ericwen/p/ShellSort_QuickSort.html
Copyright © 2011-2022 走看看