Python 快速排序 两种递归写法(用辅助空间和不用辅助空间)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gsch_12/article/details/82010702

1、快速排序
快速排序算法,简称快排,是最实用的排序算法,没有之一,各大语言标准库的排序函数也基本都是基于快排实现的。
用递归思路:
思想:随机选取一个基准,通常可以是第一个数或者最后一个数。
将剩下的数分为两个数组,小于等于这个数的划分到左数组,大于这个数划分到右数组。然后返回 左数组+基准+右数组。接着递归进去,对左、右数组做同样的操作,也就是做快排。直到子数组的长度小于等于1时,返回单独的数或者空,结束递归。

# 实现快排
def quicksort(qlist):
    if(len(qlist) <= 1):
        return qlist
    # 左子数组
    left = []
    # 右子数组
    right = []
    # 基准数
    base = qlist.pop()
    # 对原数组进行划分
    for i in qlist:
        if(i<base):
            left.append(i)
        else:
            right.append(i)
    # 递归调用
    return quicksort(left) + [base] + quicksort(right)
if __name__=='__main__':
    nums = [6,1,2,7,9,3,4,5,10,8]
    print(quicksort(nums))
    num=input().split(' ')
    print(quicksort(num))

另一个递归思路:
选取一个基准数,比如第一个数。
设置left和right两个指针,初始值left指向数组开端,right指向数组末端。如果left < right则开始大循环,设置第一个子循环里right指针从数组末端向前扫描,如果指针的数比基准大就继续向前,一旦right的指针数比基准小,则跳出循环停止扫描,将当前值赋给left指针指向的值。设置第二个子循环left从数组开始向末端扫描,如果指针当前值比基准小,则继续扫描,一旦数比基准大,停止扫描,并将当前的值赋给right指针指向的值。继续开始下一次大循环,直到left和right相等,停止循环。
循环结束后,将基准值(最开始left指针指向的值)赋值给当前right指针指向的值。
这样一趟完成了右边比base小的数和左边比base大的数的交换,交换完了,比base小的数就放在base左边,大的数放base右边。
于是开始对base左边的数组递归快排,对base右边的数组递归快排。
直到递归结束,排完数组。

# 实现快排
def quick_sort(array, left, right):
    if(left >= right):
        return
    low = left
    high = right
    key = array[low]#存储一开始最左端的值,待会交换到最后,要把值赋给右指针
    while(left < right):
        while(left < right and array[right] > key):
            right =right - 1
        array[left] = array[right]
        while(left < right and array[left] <= key):
            left = left + 1
        array[right] = array[left]
    array[right] = key
    quick_sort(array, low, left - 1)
    quick_sort(array, right + 1, high)
if __name__=='__main__':
    nums = [6,1,2,7,9,3,4,5,10,8]
    quick_sort(nums,0,len(nums)-1)
    print(nums)

各种常用排序算法

类别

排序方法

时间复杂度

空间复杂度

稳定性

复杂性

特点

最好

平均

最坏

辅助存储

 

简单

 

插入

排序

直接插入

O(N)

O(N2)

O(N2)

O(1)

稳定

简单 

 

希尔排序

O(N)

O(N1.3)

O(N2)

O(1)

不稳定

复杂

 

选择

排序

直接选择

O(N)

O(N2)

O(N2)

O(1)

不稳定

 

 

堆排序

O(N*log2N)

O(N*log2N)

O(N*log2N)

O(1)

不稳定

复杂

 

交换

排序

冒泡排序

O(N)

O(N2)

O(N2)

O(1)

稳定

简单

1、冒泡排序是一种用时间换空间的排序方法,n小时好
2
、最坏情况是把顺序的排列变成逆序,或者把逆序的数列变成顺序,最差时间复杂度O(N^2)只是表示其操作次数的数量级
3
、最好的情况是数据本来就有序,复杂度为O(n)

快速排序

O(N*log2N)

O(N*log2N) 

O(N2)

O(log2n)~O(n) 

不稳定

复杂

1n大时好,快速排序比较占用内存,内存随n的增大而增大,但却是效率高不稳定的排序算法。
2
、划分之后一边是一个,一边是n-1个,
这种极端情况的时间复杂度就是O(N^2)
3
、最好的情况是每次都能均匀的划分序列,O(N*log2N)

归并排序

O(N*log2N) 

O(N*log2N) 

O(N*log2N) 

O(n)

稳定

复杂

1n大时好,归并比较占用内存,内存随n的增大而增大,但却是效率高且稳定的排序算法。

基数排序

O(d(r+n))

O(d(r+n))

O(d(r+n))

O(rd+n)

稳定

复杂

 

注:r代表关键字基数,d代表长度,n代表关键字个数

参考:https://blog.csdn.net/bxw1992/article/details/76736117

猜你喜欢

转载自blog.csdn.net/gsch_12/article/details/82010702
今日推荐