python 快排的各种实现及优化方向

import time
import random
import sys


"""很多人提起快排和二分都觉得很容易的样子,但是让现场Code很多就翻车了,就算可以写出
个递归版本的代码,但是对其中的复杂度分析、边界条件的考虑、非递归改造、代码优化等就无
从下手,填鸭背诵基本上分分钟就被面试官摆平了。
递归的实现主要是借助系统内的栈来实现的。如果调用层级过深需要保存的临时结果和关系会非
常多,进而造成StackOverflow栈溢出。Stack一般是系统分配空间有限内存,每个系统架构默认
的栈大小不一样,比如在x86-CentOS7.x版本使用ulimit -s 查看是8192Byte。
避免栈溢出的一种办法是使用循环。

 - 掌握基准值选择对性能的影响 
 - 掌握基准值选择的多种策略 
 - 掌握尾递归的概念原理和优势
 - 数据量大和数据量小都适合用快速排序吗?
 - 快速排序的时间复杂度不是稳定的nlogn,最坏情况会变成n^2,怎么解决复杂度恶化问题?
 - 快速排序递归实现时,怎么解决递归层次过深的问题?
 - 递归过深会引发什么问题?
 - 怎么控制递归深度?如果达到递归深度了还没排完序怎么办?

STL的sort算法,数据量大时采用QuickSort快排算法,分段归并排序。一旦分段后的数据量小于
某个门槛(16),为避免QuickSort的递归调用带来过大的额外负荷,就改用Insertion Sort。
如果递归层次过深,会改用HeapSort。

""

# 左右指针法
def quick_sort1(array, low, high):
    """
    找一个基数,前面找比这个数小的数,然后从后面找比这个数大的数,然后两个数对调。
    优化方向:每次基数随机
    """
    if low < high:
        left, right = low, high
        rand = random.randint(left, right)
        array[left], array[rand] = array[rand], array[left]
        pivot = array[left]
        while left < right:
            if left < right and array[right] >= pivot:
                right -= 1
            array[left] = array[right]
            if left < right and array[right] < pivot:
                left += 1
            array[right] = array[left]

        array[left] = pivot
        quick_sort1(array, low, left -1)
        quick_sort1(array, left + 1, high)
    return array


# 前后指针法
def quick_sort2(array, low, high):
    """
    找一个基数,两个指针分别记录当前位置和上一个比基数大的数的位置,若当前位置比基数小,则换到前面
    """
    if len(array) < 2:
        return array
    if low < high:
        pivot = partition2(array, low, high)
        quick_sort2(array, low, pivot - 1)
        quick_sort2(array, pivot + 1, high)
    return array


def partition2(nums, left, right):
    pivot = nums[right]
    i = left
    for j in range(left, right):
        if nums[j] < pivot:
            nums[i], nums[j] = nums[j], nums[i]
            i += 1
    nums[i], nums[right] = nums[right], nums[i]
    return i


# 分治法
def quick_sort3(array):
    """
    选一个基数,把比这个数大的数放到这个数的左边,比这个数小的放到这个数的右边,然后在
    采用分治法对左右进行同样的操作。
    这个数最后所在的位置即为这个数在这组数中的大小排序。
    """
    if len(array) < 2:
        return array

    pivot = array[0]
    less_than_pivot = [i for i in array[1:] if i <= pivot]
    more_than_pivot = [x for x in array[1:] if x > pivot]
    return quick_sort3(less_than_pivot) + [pivot] + quick_sort3(more_than_pivot)


if __name__ == '__main__':
	sys.setrecursionlimit(100000)
	array = [random.randint(0, 10000) for _ in range(10000)]

   	s_time = time.time()
	sort_list1 = quick_sort1(array[:], 0, len(array) - 1)
	print('quick_sort1 Time used:', time.time() - s_time)
	
	s_time = time.time()
	sort_list2 = quick_sort2(array[:], 0, len(array) - 1)
	print('quick_sort2 Time used:', time.time() - s_time)
	
	s_time = time.time()
	sort_list3 = quick_sort3(array[:])
	print('quick_sort3 Time used:', time.time() - s_time)
	
	print(sorted(array) == sort_list1 == sort_list2 == sort_list3)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值