排序算法(七)——快速排序算法详解及Python实现

目录

  • 一、简介
  • 二、算法介绍
  • 三、代码实现
    • 3.1 基本实现
    • 3.2 算法优化
      • 3.2.1 采用三数取中法优化选取枢轴(partition函数)
      • 3.2.2 优化不必要的交换(partition函数)
      • 3.2.3 优化递归操作(qsort函数)
      • 3.2.4 优化小数组时的排序方案
  • 排序算法系列——相关文章

一、简介

快速排序算法最早是由图灵奖获得者Tony Hoare设计的,被列为20世纪十大算法之一。属于交换排序类,是冒泡排序算法的升级,是一种不稳定排序算法,其时间复杂度为O(nlogn)

二、算法介绍

快速排序算法的基本思想是:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可对这两部分记录继续进行排序,以达到整个序列有序的目的。

  1. 选取数组中第一个元素作为pivot key(枢轴),即令pv = li[low],然后从数组的两端向中间扫描;
  2. low < highli[high] >=pv时,high = high - 1,直到pv > li[high],然后交换li[low]li[high]的位置(通过这种操作将比pv大的值移动到pv右边);
  3. 然后继续循环,当low < highli[ow] < pv时,low = low + 1,直至li[low] > pv,然后交换li[low]li[high]的位置(通过这种操作将比pv小的值移动到pv左边);
  4. 循环结束后,low即为pivot的值,此时,在li[pivot]左边的值都小于li[pivot],在li[pivot]右边的值都大于li[pivot]
  5. 根据pivo将数组分为左右两部分,重复进行上述工作,直至最终获得有序数组。

三、代码实现

3.1 基本实现

def partition(li, low, high):
    """
    将low所在位置值作为pv,从两端同时遍历,将比pv小的值移动到pivot左侧,将比pv大的值移动到pivot右侧,最终返回pivot,也就是low
    """
    pv = li[low]
    while low < high:
        while low < high and li[high] >= pv:
            high -= 1
        li[low], li[high] = li[high], li[low]  # 交换位置
        while low < high and li[low] <= pv:
            low += 1
        li[low], li[high] = li[high], li[low]  # 交换位置
    return low  # 返回pivot值

def qsort(li, low, high):
    if low < high:
        pivot = partition(li, low, high)
        qsort(li, low, pivot)
        qsort(li, pivot+1, high)
    return li

def quickSort(li):
    """
    快速排序,属于交换排序类,不稳定排序,利用递归函数sort实现
    平均时间复杂度O(n*logn),最坏情况时间复杂度为O(n2)
    """
    return qsort(li, 0, len(li)-1)

if __name__ == '__main__':
    li = [90, 10, 50, 80, 30, 70, 40, 60, 20]
    print('快速排序:', quickSort(li.copy()))

3.2 算法优化

3.2.1 采用三数取中法优化选取枢轴(partition函数)

def partition_optimize_pivot(li, low, high):
    """
    在partition函数的基础上,优化pivot选取方式
    """
    mid = (low + high) // 2
    # ----通过下述代码将li[low]调整为数组左中右三个值的中间值---- #
    if li[low] > li[high]:
        li[low], li[high] = li[high], li[low]  # 交换位置
    if li[mid] > li[high]:
        li[mid], li[high] = li[high], li[mid]  # 交换位置
    if li[mid] > li[low]:
        li[mid], li[low] = li[low], li[mid]  # 交换位置
    pv = li[low]
    # ---------------------------------------------------- #
    while low < high:
        while low < high and li[high] >= pv:
            high -= 1
        li[low], li[high] = li[high], li[low]  # 交换位置
        while low < high and li[low] < pv:
            low += 1
        li[low], li[high] = li[high], li[low]  # 交换位置
    return low  # 返回pivot值

3.2.2 优化不必要的交换(partition函数)

在3.1中的代码中,li[low], li[high] = li[high], li[low] # 交换位置一行,会多次移动pv值,因此可将pv值直接移动到最终位置,减少交换次数以提升性能。

def partition_optimize_swap(li, low, high):
    """
    在partition函数的基础上,减少不必要的交换以提高性能
    """
    pv = li[low]
    while low < high:
        while low < high and li[high] >= pv:
            high -= 1
        li[low] = li[high]
        while low < high and li[low] < pv:
            low += 1
        li[high] = li[low]
    li[low] = pv
    return low  # 返回pivot值

3.2.3 优化递归操作(qsort函数)

def qsort(li, low, high):
    while low < high:
        pivot = partition(li, low, high)
        qsort(li, low, pivot)
        low = pivot + 1  # 尾递归优化
    return li

3.2.4 优化小数组时的排序方案

由于快速排序中,大量使用了递归操作,对于数组特别小的情况,快速排序反而不如直接插入排序效果好,因此可以结合快速排序和直接插入排序提高整体排序效率。直接插入排序代码参见博客排序算法(三)——直接插入排序算法详解及Python实现


以上,欢迎指正交流~

参考资料:
[1] 《大话数据结构》


排序算法系列——相关文章

[1] 排序算法(一)——冒泡排序算法详解及Python实现
[2] 排序算法(二)——简单选择排序算法详解及Python实现
[3] 排序算法(三)——直接插入排序算法详解及Python实现
[4] 排序算法(四)——希尔排序算法详解及Python实现
[5] 排序算法(五)——堆排序算法详解及Python实现
[6] 排序算法(六)——归并排序算法详解及Python实现
[7] 排序算法(七)——快速排序算法详解及Python实现

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