python-高级排序(二)

快速排序

快速排序名字可不是盖的,很多程序语言标准库实现的内置排序都要它的身影, 我们就直奔主题吧。和归并排序一样,快排也是一种分而治之(divide
and
conquer)的策略。归并排序把数组递归成只有单个元素的数组,之后再不断两两合并,最后得到一个有序的数组。这里的递归基本条件就是只包含一个元素的数组,当数组只包含一个元素的时候,我们可以认为它本来就是有序的(当然空数组也不用排序).


快排的工作过程其实比较简单,三步走:

1.选择基准值 pivot 将数组分成两个子数组:小于基准值的元素和大于基准值的元素。这个过程称之为 partition
2.对这两个子数组进行快速排序
3.合并结果


根据这个想法我们可以快速写出快排的代码,简直就是在翻译上边的描述:

# -*- coding:utf-8 -*-

def quicksort(array):
    if len(array) < 2:
        return array
    else:
        pivot_index = 0
        pivot = array[pivot_index]
        #构造一个小于基准值的元素数组
        less_port = [i for i in array[pivot_index+1:] if i <= pivot]
        #构造一个大于基准值的元素数组
        great_sort = [i for i in array[pivot_index+1:] if i > pivot]
        return quicksort(less_port) + [pivot] + quicksort(great_sort)


def test_quicksort():
    import random
    seq = list(range(10))
    random.shuffle(seq)
    assert quicksort(seq) == sorted(seq)

是不是很简单,下次面试官让你手写快排你再写不出来就有点不太合适啦。当然这个实现也有两个不好的地方:

1.第一是它需要额外的存储空间,我们想实现inplace原地排序
2.第二是它的partition操作每次都要两次遍历整个数组,我们想改善一下

这里我们来优化一下它,实现inplace排序并且改善下partition操作.

这里写图片描述





# -*- coding:utf-8 -*-

def quicksort(array):
    if len(array) < 2:
        return array
    else:
        pivot_index = 0
        pivot = array[pivot_index]
        less_port = [i for i in array[pivot_index+1:] if i <= pivot]
        great_sort = [i for i in array[pivot_index+1:] if i > pivot]
        return quicksort(less_port) + [pivot] + quicksort(great_sort)

'''
    方法实现:
        第一个元素作为 pivot主元,
        将比主元值小的元素放在主元左边
        将比主元值大的元素放在主元右边
'''
def partition(array,beg,end):
    pivot_index = beg
    pivot = array[pivot_index]
    left = pivot_index + 1
    right = end - 1
    while True:
        while left <= right and array[left] < pivot:
            left += 1

        while right >= left and array[right] >= pivot:
            right -= 1

        if left > right:
            break
        else:
            array[left],array[right] = array[right],array[left]

    array[pivot_index],array[right] = array[right],array[pivot_index]
    return right

def test_partition():
    l = [4,1,2,8]
    assert partition(l,0,len(l)) == 2
    l = [1,2,3,4]
    assert partition(l,0,len(l)) == 0
    l = [4,3,2,1]
    assert partition(l,0,len(l)) == 3


def quicksort_inplace(array,beg,end):
    if beg < end:
        pivot = partition(array,beg,end)
        quicksort_inplace(array,beg,pivot)
        quicksort_inplace(array,pivot+1,end)

def test_quicksort_inplace():
    import random
    seq = list(range(10))
    random.shuffle(seq)
    print(seq)
    quicksort_inplace(seq,0,len(seq))
    print(seq)




猜你喜欢

转载自blog.csdn.net/qq_39469688/article/details/81632837
今日推荐