python-排序算法(二)、快速排序

一、快速排序 

快速排序的思路:

1、对于列表li,第一次取一个元素P(第一个元素或倒数第一个元素),使元素归位

排序前:

[3, 5, 8, 1, 2, 9, 4, 7, 6]

2、通过算法函数将P分成两部分,左部分都比P小,右部分都比P大

6归位后:

[3, 5, 4, 1, 2, 6, 9, 7, 8]

3、将列表的左边部分[3, 5, 4, 1, 2],右边部分[9, 7, 8]进行递归调用归位,即可完成排序

排序后:

  [1, 2, 3, 4, 5, 6, 7, 8, 9]

    

1、归位算法函数

思路

1、取列表倒数一个元素,暂存tmp变量,此时列表倒数第一个位置为空

2、取变量left=0,从列表左边开始遍历列表,判断当前的数是否小于tmp,如果小于则继续往右走,如果大于tmp,则将当前的数移存到right

3、取变量right=列表长度。从列表右边开始倒序遍历列表,判断当前的数是否大于tmp,如果大于则继续往左走(right-1),如果小于tmp,则将当前的数移存到left,当前数的当前位置为空

4、直到left=right时即完成归位

def _homing(li, left, right):
    tmp = li[right]  # 暂存倒数第一个数到tmp
    while left < right:  # 结束条件
        # 此时右边有空位,则从左边开始遍历,找寻大于tmp的数
        while left < right and li[left] <= tmp:
            left += 1
        li[right] = li[left]  # 循环完后,此时li[left]>tmp ,则将li[left]移存li[right]
        # 此时左边有空位,则从右边开始遍历,找寻小于tmp的数
        while left < right and li[right] >= tmp:
            right -= 1
        li[left] = li[right]  # 循环完后,此时li[right]<tmp ,则将li[right]移存li[left]
    li[left] = tmp  # 当left=right时,循环结束,此时将tmp归位至li[left]
    return left

2、递归完成排序 


def _quick_sort(li, left, right):
    if left < right:
        mid = _homing(li, left, right) # 第一次归位将li分成左右部分,返回中间数的下标
        _quick_sort(li, left, mid - 1)  # 将左边部分进行归位
        _quick_sort(li, mid + 1, right) # 将右边部分进行归位


li = [3, 5, 8, 1, 2, 9, 4, 7, 6]
_quick_sort(li, 0, len(li)-1)
print(li)


# 结果
[1, 2, 3, 4, 5, 6, 7, 8, 9]

时间复杂度

         最好情况:O(nlogn)

         最坏情况:O(n²)

3、相比冒泡排序 

import copy
import time
import sys
import random

sys.setrecursionlimit(100000)


def cal_time(func):
    def inner(*args, **kwargs):
        strat = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print('%s执行时间:%s' % (func.__name__, end - strat))
        return result

    return inner



def _homing(li, left, right):
    tmp = li[right]  # 暂存倒数第一个数到tmp
    while left < right:  # 结束条件
        # 此时右边有空位,则从左边开始遍历,找寻大于tmp的数
        while left < right and li[left] <= tmp:
            left += 1
        li[right] = li[left]  # 循环完后,此时li[left]>tmp ,则将li[left]移存li[right]
        # 此时左边有空位,则从右边开始遍历,找寻小于tmp的数
        while left < right and li[right] >= tmp:
            right -= 1
        li[left] = li[right]  # 循环完后,此时li[right]<tmp ,则将li[right]移存li[left]
    li[left] = tmp  # 当left=right时,循环结束,此时将tmp归位至li[left]
    return left


def _quick_sort(li, left, right):
    if left < right:
        mid = _homing(li, left, right)  # 第一次归位将li分成左右部分,返回中间数的下标
        _quick_sort(li, left, mid - 1)  # 将左边部分进行归位
        _quick_sort(li, mid + 1, right)  # 将右边部分进行归位


@cal_time
def quick_sort(li):
    _quick_sort(li, 0, len(li) - 1)


# 以上是快速排序
# 以下的冒泡排序
@cal_time
def bubble_sort(li):
    for i in range(len(li) - 1):
        exchange = False
        for j in range(len(li) - i - 1):
            if li[j] > li[j + 1]:
                li[j], li[j + 1] = li[j + 1], li[j]
                exchange = True
        # print("第%s趟" % i, li)
        if exchange is False:
            return


li = list(range(10000, 0, -1))

random.shuffle(li)

li1 = copy.deepcopy(li)
li2 = copy.deepcopy(li)

quick_sort(li1)
bubble_sort(li2)
print(li1)
print(li2)

结果:

quick_sort执行时间:0.015630722045898438
bubble_sort执行时间:3.1336376667022705

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值