算法和数据结构系列:快速排序——Python实现

写了两个版本:

1:基准数是随机取的,然后把它放在列表最后,开始从列表第一项比较。

从第一项开始,如果该元素大于基准数,不进行任何操作,开始比较下一项(l += 1);如果该元素小于基准数,则要往前排,和前面大于基准数的元素进行交换,就是小的元素要不断往前插,大的数就会不断被扔向后面。注意这个过程就需要两个索引:一个指向前面小元素和大元素的分界线(small),一个指向当的元素(l)。small的初始值为-1,l的初始值为0,如果和基准数比较的当前元素(索引值为l的元素)是小于基准数的,small也要加1,然后small和l指向的两个元素进行交换;如果当前元素大于基准数,接着向下遍历,此时small不变,因为并没有找到比基准数小的元素。最后遍历完整个列表,small再加1表示排在第一个的大于基准数的元素的索引(不加1的时候是排在最后的小于基准数的元素索引),然后和列表最后一项交换,即把大于基准数的元素扔到最后一项,把之前保存在最后一项的基准数插入到小于它的和大于它的元素之间。这样所有小于基准数的元素都在其前面,大于它的元素都在它后面。然后递归分别对前面和后面的子列表排序。代码如下:

def quickSort(lista):
    if len(lista) > 1:
        m = random.choice(lista)
        p = lista.index(m)
        l = 0
        small = -1
        lista[-1], lista[p] = lista[p], lista[-1]
        while l < (len(lista)-1):
            if lista[l] < m:
                small += 1
                if small != l:
                    lista[l], lista[small] = lista[small], lista[l]
            l += 1
        small += 1
        lista[small] ,lista[-1] = lista[-1], lista[small]
        lista[:small] = quickSort(lista[:small])
        lista[small+1:] = quickSort(lista[small+1:])
    return lista

2:这个方法中直接取列表第一个元素作为基准数,然后分别从前和后两个方向寻找异常值:从前向后的遍历中大于基准数的元素是异常值,从后向前的遍历中小于基准数的元素是异常值。遍历过程中要注意保证两个索引未交叉,交叉则表明遍历结束,所有元素都已经检查过了。具体操作中,是从前向后先找到一个异常值,然后开始从后向前找到一个异常值,然后两个元素交换,再开始下一轮寻找(依然是先从前向后,接着上次的位置)。整个列表遍历结束后,要把基准数放到正确的位置,因此列表第一项和右索引的元素进行一次交换,交换后同样递归排序前半部分和后半部分。具体代码如下:

def quickSort1(lista):
    if len(lista) > 1:
        p = lista[0]
        l = 0
        r = len(lista) - 1
        done =False
        while not done:
            while (l <= r) and lista[l] <= p:
                l += 1
            while (l <= r) and lista[r] >= p:
                r -= 1
            if l <= r:
                lista[l], lista[r] = lista[r], lista[l]
            else: 
                done = True
        lista[l-1], lista[0] = lista[0], lista[l-1]
        lista[:l-1] = quickSort1(lista[:l-1])
        lista[l:] = quickSort1(lista[l:])
    return lista

验证过程如下:

for i in range(10):
    lista = [random.choice(range(100)) for j in range(15)]
    print('before sort:', lista)
    listsort1 = quickSort(lista)
    listsort2 = quickSort1(lista)
    print('after sort:', listsort2)
    print('two function eq?', listsort2 == listsort1)

生成10个列表,每个列表的每个元素都是从0-99中随机抽取的,每个列表共15个元素。对这10个列表用两种方法分别进行排序得到listsort1和listsort2,输出排序后的列表并判断两个排序结果是否完全一致,输出如下所示:

before sort: [37, 90, 88, 33, 33, 75, 4, 48, 72, 30, 43, 0, 39, 31, 35]
after sort: [0, 4, 30, 31, 33, 33, 35, 37, 39, 43, 48, 72, 75, 88, 90]
two function eq? True
before sort: [70, 86, 62, 0, 72, 2, 28, 6, 88, 74, 74, 20, 7, 41, 40]
after sort: [0, 2, 6, 7, 20, 28, 40, 41, 62, 70, 72, 74, 74, 86, 88]
two function eq? True
before sort: [4, 83, 11, 16, 76, 25, 6, 50, 77, 81, 28, 83, 53, 58, 24]
after sort: [4, 6, 11, 16, 24, 25, 28, 50, 53, 58, 76, 77, 81, 83, 83]
two function eq? True
before sort: [98, 75, 89, 24, 76, 49, 21, 22, 54, 30, 43, 27, 55, 54, 26]
after sort: [21, 22, 24, 26, 27, 30, 43, 49, 54, 54, 55, 75, 76, 89, 98]
two function eq? True
before sort: [93, 68, 58, 15, 82, 28, 8, 19, 33, 24, 80, 74, 49, 60, 33]
after sort: [8, 15, 19, 24, 28, 33, 33, 49, 58, 60, 68, 74, 80, 82, 93]
two function eq? True
before sort: [91, 38, 18, 28, 45, 69, 84, 47, 56, 55, 21, 33, 23, 61, 57]
after sort: [18, 21, 23, 28, 33, 38, 45, 47, 55, 56, 57, 61, 69, 84, 91]
two function eq? True
before sort: [19, 14, 86, 4, 56, 36, 77, 14, 56, 53, 49, 88, 20, 85, 88]
after sort: [4, 14, 14, 19, 20, 36, 49, 53, 56, 56, 77, 85, 86, 88, 88]
two function eq? True
before sort: [80, 54, 67, 61, 9, 14, 90, 39, 74, 24, 97, 93, 93, 39, 92]
after sort: [9, 14, 24, 39, 39, 54, 61, 67, 74, 80, 90, 92, 93, 93, 97]
two function eq? True
before sort: [62, 93, 45, 6, 23, 60, 59, 66, 84, 96, 41, 33, 76, 39, 47]
after sort: [6, 23, 33, 39, 41, 45, 47, 59, 60, 62, 66, 76, 84, 93, 96]
two function eq? True
before sort: [21, 6, 78, 59, 8, 53, 44, 92, 38, 42, 78, 72, 9, 22, 69]
after sort: [6, 8, 9, 21, 22, 38, 42, 44, 53, 59, 69, 72, 78, 78, 92]
two function eq? True
>>> 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值