快速排序Python代码实现

    快速排序(Quick Sort)是通过分治的思想来进行排序。它的主要思想是:取数组中的一个数作为

基准值(往往取数组中的第一个数),把所有小于基准值的数都放在它的左侧,再把所有大于基准值的数都放在它的右侧。随后,对基准值左右两侧的数组分别进行快速排序。

    快速排序的平均时间复杂度是O(nlgn),最好情况下的时间复杂度是O()。最坏情况下,快速排序的时间复杂度可能退化为O(n^2),但这种情况很少见。快速排序是一个不稳定的算法,如果使用得当,快速排序的速度可以达到归并排序和堆排序的数倍,所以快速排序是一种极其常用的算法。

写了三种方法,思路都是一样的,具体细节不一样。

第一种方法比较简单,也好理解

nums = [5, 6, 4, 5, 3, 1, 8, 9, 7]

def QuickSort(num):
    # 若列表长度为1,直接输出不用排序  
    if len(num) <= 1:                        
        return num
    # 取数组的第一个数作为基值
    key = num[0]  
    # 定义空列表用来储存大于/小于/等于基准值的元素                          
    llist, mlist, rlist = [], [], []  
    # 定义空列表用来储存大于/小于/等于基准值的元素     
    for i in range(0, len(num)):            # 遍历列表,把元素归类到三个列表中
        if num[i] < key:
            llist.append(num[i])
        elif num[i] > key:
            rlist.append(num[i])
        else:
            mlist.append(num[i])
    # 对左右两个列表进行快排,拼接三个列表并返回
    return QuickSort(llist) + mlist + QuickSort(rlist)  


print(QuickSort(nums))

    以这种方法来实现快速排序需要额外的开辟空间给用于归类的列表。并且相似的思路用于其他的编程语言是效率低。

    那么,我们就需要对这种方法来进行优化。此时,用一个变量来储存基准值,然后用两个指针,一个在最左边从左往右遍历,另一个在最右边从又往左遍历。开始遍历的时候可以把基准值在数组中的位置,也就是第一个元素,视作一个没有元素的空位。

第一步,先移动右指针,从右往左移动,直到指针指向的元素小于基准值为止。并把右指针指向的值赋给左指针指向的位置

第二部,移动左指针,从左往右移动,直到指针指向的元素大于等于基准值时停下。并把左指针指向的值赋给右指针指向的位置。

第三步,重复以上操作,不断交替移动左右指针并赋值。

第四步,当左右指针重合时,所有必要的移动都已经完成。左右指针共同指向的位置就是基准值在有序数组中的位置。它的值大于它左侧所有的元素并小于它右侧所有的元素。剩余操作为递归排序左右子数组,直到全部数组排序完成。

# QSort
nus = [4, 5, 1, 2, 3, 5, 4, 1]

# left,right分别为子数组中第一个元素和最后一个元素在原数组中的位置
def QSort(left, right):
    # 边界条件               
    if left >= right:                
        return
    # 初始化左右指针的初始值
    l, r, key = left, right, nus[left] 
    # 调整元素的位置 
    while l < r:                     
        while l < r and nus[r] >= key:
            r -= 1
        nus[l] = nus[r]
        while l < r and nus[l] <= key:
            l += 1
        nus[r] = nus[l]
    # 把基准值赋给左右指针共同指向的位置
    nus[r] = key 
    # 对左侧数组排序                   
    QSort(left, l-1)  
    # 对右侧数组排序              
    QSort(l+1, right)               
QSort(0, len(nus) - 1)
print(nus)

相对于第一种方法,这种方法解决了需要开辟空间的问题,元素与元素之间在原来的数组内部进行位置的交换,。但是这中方法没有采用直接将数组传入函数的方法,而是把子数组第一个和最后一个元素的位置穿入函数中,就导致了在实际使用的时候并不方便,因为每次使用的时候就需要调整。

这就需要第三种方法,既包含了前两种方法的优点使用起来也非常方便,首先这种方法需要需要把数组传入函数当中,然后再运用指针交换的形式来进行快速排序。

def QSort(lst, left, right):
    if left >= right:
        return
    l, r, key = left, right, lst[left]
    while l < r:
        while l < r and lst[r] >= key:
            r -=1
        lst[l] = lst[r]
        while l < r and lst[l] < key:
            l += 1
        lst[r] = lst[l]
    lst[l] = key
    QSort(lst, left, l-1)
    QSort(lst, l+1, right)
    return lst

nus = [4, 5, 1, 2, 3, 5, 4, 1]
print(QSort(nus, 0, len(nus) - 1))

  • 14
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰基客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值