数据结构与算法:快速排序

经典快排

首先任意选取一个数据作为关键数据,然后将所有比它小的数都放到它左边,所有比它大的数都放到它右边,这个过程称为一趟快速排序。然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归的进行直到整个数组有序。可以发现其实每一趟快速排序都是在做一次荷兰国旗的划分。关于荷兰国旗问题可以查看这里。

算法实现

在这里我们每次都选取序列的最后一个值作为划分的关键数据。
算法实现不是很难,先对数组进行划分,然后对数组左侧进行递归,对数组右侧进行递归。代码如下:

public static void quickSort(int[] arr,int left,int right) {
        if(left < right) {
            int[] p = partition(arr,left,right);    //划分
            
            quickSort(arr,left,p[0]-1);     //左递归
            quickSort(arr,p[1],right);  //右递归
        }
    }
    
    /*
     * 这里是荷兰国旗的划分,且以arr数组的最后一个数arr[right]作为划分的值。
     * */
    private static int[] partition(int[] arr,int left, int right) {
        
        int less = left - 1;
        int more = right + 1;
        
        while(left < more) {
            
            if(arr[left] < arr[right]) {
                
                swap(arr,++less,left++);
                
            }else if(arr[left] > arr[right]) {
                
                swap(arr,--more,left);
                
            }else {
                
                left++;
                
            }
        }
        return new int[] {less+1,more};
    }
    
    private static void swap(int[] arr,int i,int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
时间复杂度

排序的效率与数组的数据状况有关。
在极端的数据状况下,例如:1 2 3 4 5 6 7 8 9。我们每次一最后一个数据作为划分值,则每次只搞定最后一个数据,而每一次执行partition函数都要付出O(N)的时间代价,一共有N个数据,则时间复杂度为O(N^2);
在最理想的数据状况下,如下所示:等于划分值的区域在中间,其两侧被划分为等规模的样本空间,其花费时间为T(N) = 2T(N/2) + O(N);其最终求得的时间复杂度为O(N.logN)。关于递归行为时间复杂度的分析

 _____________________________________
|      N/2      | =X |     N/2        |
|_______________|____|________________|
稳定性

多个相同的值的相对位置也许会在划分过程中产生变动,所以快速排序不是一种稳定的排序算法。

你可能感兴趣的:(数据结构与算法:快速排序)