【排序算法】5.快速排序

快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

步骤为:

  • 从数列中挑出一个元素,称为"基准"(pivot),
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
  • 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

java 的几种实现:

public class QuickSortTest {
    public static void main(String[] args) {
        StopWatch stopWatch = new StopWatch();
        int[] input1 = {2,5,4,89,20,89,6,0,54,78,2};
        stopWatch.start();
        quickSortByMiddle(input1, 0, input1.length-1);
        PrintUtils.print(input1);
        stopWatch.stop();

        stopWatch.start();
        quickSortByMiddle(input1, 0, input1.length-1);
        PrintUtils.print(input1);
        stopWatch.stop();

        int[] input2 = {2,5,4,89,20,89,6,0,54,78,2};
        stopWatch.start();
        quickSortByMiddle1(input2, 0, input2.length-1);
        PrintUtils.print(input2);
        stopWatch.stop();

        int[] input3 = {2,5,4,89,20,89,6,0,54,78,2};
        stopWatch.start();
        quick_sort(input3, 0, input3.length-1);
        PrintUtils.print(input3);
        stopWatch.stop();
        System.out.println(stopWatch);
    }

    /**
     * 以中间位置为基准,关注指针,当 pivot 发生交换时,移动 pivot 指针
     * @param arr
     * @param left
     * @param right
     */
    public static void quickSortByMiddle(int[] arr, int left, int right){
        if(left >= right){
            return;
        }
        int pivotPointer = (right + left) / 2;
        int l = left;
        int r = right;
        while (l < r){
            //从左向右查找,找到一个大于 pivot 的值或 l == pivot 为止
            while(l < pivotPointer && arr[l] < arr[pivotPointer]){
                l++;
            }
            //从右向左查找,找到一个小于 pivot 的值或 r == pivot 为止
            while (r > pivotPointer && arr[r] > arr[pivotPointer]){
                r--;
            }
            //左侧找到的数,和右侧找到的数进行交换
            int temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            //移动pivot
            if (l == pivotPointer){
                pivotPointer = r;
            }else if (r == pivotPointer){
                pivotPointer= l;
            }
            //移动左右指针,进入下一轮
            if (l < pivotPointer){
                l++;
            }
            if (r > pivotPointer){
                r--;
            }
        }
        /**
         * 说明左右两个指针都已经移动到了pivot
         * pivot左侧都小于pivot,右侧都大于pivot
         * 所以无需交换
         */
        if (r==l){
            quickSortByMiddle(arr, left, pivotPointer - 1);
            quickSortByMiddle(arr, pivotPointer + 1, right);
        }

    }


    /**
     * 以中间位置为基准,忽略指针,只关心 pivot 的值
     * @param arr
     * @param left
     * @param right
     */
    public static void quickSortByMiddle1(int[] arr, int left, int right){
        int pivot = arr[(right + left) / 2];
        int l = left;
        int r = right;
        while (l < r){
            //从左向右查找,找到一个大于 pivot 的值或 l == pivot 为止
            while(l < r && arr[l] < pivot){
                l++;
            }
            //从右向左查找,找到一个小于 pivot 的值或 r == pivot 为止
            while (l < r && arr[r] > pivot){
                r--;
            }
            if (l >= r){
                break;
            }
            //左侧找到的数,和右侧找到的数进行交换
            int temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            if (arr[l]==pivot){
                l++;
            }
            if (arr[r]==pivot){
                r--;
            }
        }
        if (left == r){
            r--;
            l++;
        }
        if (left < r){
            quickSortByMiddle1(arr, left, r);
        }
        if (right > l){
            quickSortByMiddle1(arr, l, right);
        }

    }

    /**
     * 以左侧第一个元素作为基准,这个写法还真是简洁啊~
     * @param myList
     * @param first
     * @param last
     */
    public static void quick_sort(int[] myList,int first,int last){
        if(first>=last){
            return;
        }
        int mid_value = myList[first];
        int low = first;
        int high = last;
        while(low=mid_value){
                high--;
            }
            myList[low] = myList[high];
            while(low

时间复杂度

  • 最优时间复杂度:O(nlogn)
  • 最坏时间复杂度:O(n2)
  • 稳定性:不稳定

你可能感兴趣的:(【排序算法】5.快速排序)