zoukankan      html  css  js  c++  java
  • Quick Sort

    输入:一个待排序的数组A以及排序范围[left, right]。

    输出:排序后的数组。

    算法思想

    快速排序算法属于分治算法:将数组的最后一个元素与其他元素进行一系列的比较与交换(划分),插入到这个元素在排好序后所处的位置。此时,该元素的左边的元素都比该元素小,右边的元素都比该元素大,则该问题被划分成了三个小问题:1) 该元素左边的待排序子数组 ;2) 该元素右边的待排序子数组;3) 该元素(已经被排序)。

    划分

    算法导论中对划分的伪码描述如下(数组下标从1开始,而不是0):

    PARTITION(A, left, right):
        x = A[right]
        i = left - 1
        for j = left to r - 1:
            if A[j] <= x:
                i = i + 1
                exhcange A[i] with A[j]
        exchange A[i + 1] with A[right]  // 将最后一个元素插入到正确的位置
        return i + 1
    

    该伪代码在for循环中将已经比较过的子数组分成两个部分,A[0, i]为比A[right]小的元素,A[i + 1, j - 1]为比A[length - 1]大的元素。若A[j] <= A[right],则A[0, i]扩充到A[0, i + 1],否则A[i + 1, j - 1]扩充到[i + 1, j]。

    例子

    输入:A = [5, 2, 6, 8, 1, 3, 9, 7, 4],left = 0,right = 8

    1. 5 > 4,不交换,A = [5, 2, 6, 8, 1, 3, 9, 7, 4];
    2. 2 < 4,交换,A = [2, 5, 6, 8, 1, 3, 9, 7, 4];
    3. 6 > 4,不交换,A = [2, 5, 6, 8, 1, 3, 9, 7, 4];
    4. 8 > 4,不交换,A = [2, 5, 6, 8, 1, 3, 9, 7, 4];
    5. 1 < 4,交换,A = [2, 1, 6, 8, 5, 3, 9, 7, 4];
    6. 3 < 4,交换,A = [2, 1, 3, 8, 5, 6, 9, 7, 4];
    7. 9 > 4,不交换,A = [2, 1, 3, 8, 5, 6, 9, 7, 4];
    8. 7 > 4,不交换,A = [2, 1, 3, 8, 5, 6, 9, 7, 4];
    9. 此时蓝色部分都比4小,红色部分都比4大,将4与8进行交换,得到A = [2, 1, 3, 4, 5, 6, 9, 7, 8]即完成第一次插入,此后只需要对蓝色部分与红色部分分别递归地进行上述操作即可完成整个数组的排序。

    快速排序完整算法(Python实现)

    from random import randint
    from random import uniform
    
    def quick_sort(array_to_sort, left, right):
        array_to_sort = array_to_sort.copy()
        if left >= right:
            return array_to_sort  # needn't to sort
        
        stack = [left, right]
        while stack:
            high = stack.pop(-1)
            low = stack.pop(-1)
            if low >= high:
                continue
            
            random_number = int(uniform(low, high))  # randomization
            array_to_sort[random_number] , array_to_sort[high] = array_to_sort[high], array_to_sort[random_number]
            pivot_element = array_to_sort[high]
            i = low - 1
            for j in range (low, high):
                if array_to_sort[j] <= pivot_element:
                    i = i + 1
                    array_to_sort[j], array_to_sort[i] = array_to_sort[i], array_to_sort[j]
            array_to_sort[i + 1], array_to_sort[high] = array_to_sort[high], array_to_sort[i + 1]
            stack.extend([low, i, i + 2, high])
        
        return array_to_sort
    
    if __name__ == '__main__':
        array_size = int(input("Please input the length of array:"))
        array_to_sort = [randint(0, 1000) for i in range (0, array_size)]
        print("Init	array:", array_to_sort)
        
        # start sort
        print("
    
    ")
        print("####################")
        print("## Start sorting! ##")
        print("####################")
        print("")
        
        print("Quick		 sort:", quick_sort(array_to_sort, 0, len(array_to_sort) - 1))
    

    时间复杂度

    设对一个长度为n的数组进行快速排序需要(T(n))的时间,由于该算法将待排序数组划分成两个未排序子数组以及一个单独的元素,我们可以假设每次划分都从中间进行划分,则对每个子数组的排序所消耗的时间近似等于(T(frac{1}{2}))。每次划分都需要遍历整个数组,耗时(O(n))。综上,有:

    [T(n) = 2T(frac{1}{2}) + n ]

    这个递归定义的方程可以使用Master定理进行求解,最终可得时间复杂度为(O(nlog_2n))

  • 相关阅读:
    洛谷 P1401 城市(二分+网络流)
    洛谷 P2057 善意的投票(网络流最小割)
    洛谷 P1402 酒店之王
    二分图最大匹配的一些证明
    P2764 最小路径覆盖问题(网络流24题之一)
    洛谷 P2055 [ZJOI2009]假期的宿舍
    P2891 [USACO07OPEN]吃饭Dining(最大流+拆点)
    洛谷P1345 [USACO5.4]奶牛的电信(最小割)
    网络流24题之星际转移问题(洛谷P2754)
    LeetCode Unique Binary Search Trees
  • 原文地址:https://www.cnblogs.com/angiejc/p/11617763.html
Copyright © 2011-2022 走看看