快排及优化

思路:

快速排序的本质就是选取一个基准数,通过一次快排把基准数大的都放在基准数的左边,把比基准数小的放在基准数的右边,这样就找到了基准数在数组中的正确位置。
然后可以用递归的方式分别对前半部分和后半部分排序,最终实现整体数组有序。

快排是不是稳定排序?

所谓排序的稳定性,就是指在排序过程中,在对某关键字排序后会不会改变其他关键字的顺序。快排会改变,所以不是稳定排序。

代码:

常规代码1:

def AdjustPartition(list1,low,high):
    if low < high:
        left = low
        right = high
        key = list1[left]
        while left < right:
            while left < right and list1[right] >= key:
                right = right - 1
            list1[left] = list1[right]
            while left < right and list1[left] <= key:
                left = left + 1
            list1[right] = list1[left]
        list1[left] = key
        AdjustPartition(list1,low,left-1)
        AdjustPartition(list1,left+1,high)
    return list1

常规代码2:

def quick_sort(arr):
    if len(arr) < 2:
        return arr
    key = arr[0]  # 以第一个关键字作为基准数
    left, right = [], []
    arr.remove(key)
    for item in arr:
        if item >= key:
            right.append(item)
        else:
            left.append(item)
    return quick_sort(left) + [key] + quick_sort(right)

python一行代码实现快排:

def quick_sort(a):
    if len(a) > 1:
        return quick_sort([i for i in a[1:] if i <= a[0]]) + [a[0]] + quick_sort([i for i in a[1:] if i > a[0]])
    else:
        return a

转化为一行:

quick_sort = lambda a:a if len(a) <= 1 else quick_sort([i for i in a[1:] if i <= a[0]]) + \
[a[0]] + quick_sort([i for i in a[1:] if i > a[0]])

快排优化

如果数组元素是随机的,那么程序的运行时间不会有太大的波动。如果数组元素已经基本有序时,此时的固定基准划分就容易产生最坏的情况,即快速排序变成冒泡排序,时间复杂度为O(n2n^{2})。
eg: 序列1 2 3 6 12 18,如果用固定基准进行快排:(【】内为基准数)
第一趟:【1 】2 3 6 12 18
第二趟:1【 2】 3 6 12 18
第三趟:1 2 【3】 6 12 18
第四趟:1 2 3 【6】 12 18
第四趟:1 2 3 6 【12】 18

快排基准的选择:

(1)固定基准
比如每次以第一个关键字作为基准数。可能会退化为冒泡排序。
(2)随机基准
可以利用随机函数随机生成在[low,high]范围内的数作为基准数的下标。
(3)三数取中
随机基准选取的随机性,因此即使是同一个数组每次效率也是不一样的,此时可以选择三数取中的方法选取基准数。它的思路是:选取数组开头,中间和结尾的元素去比较,选择中间的值作为快排的基准。这种方式既能解决待排数组基本有序的情况,而且选取的基准也不是随机的。

eg:序列1 2 3 6 12 18,30,如果用三数取中进行快排:
    因为:
    数组开头是1,中间是6,结尾是30
    所以:
    所以基准数选择6进行快排。

快排优化方案

  1. 在数组长度大于某一个阈值范围时,使用递归快排,当数据长度小于阈值时,使用插入排序。因为处理较短序列时插入排序效果更好。
  2. 在partition中选取基准数时,选取三路取中。
  3. 进行三路快排优化。即将数组划分为左边小于基准数,中间等于基准数,右边大于基准数,这样两端递归时可以缩小递归数组的大小。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章