python排序(快速排序、归并排序、堆排序)

排序是必须掌握的基本算法,在面试题也经常考到,这里写一下python的几种常用排序的写法。

快速排序

写法一

def quickSort(array,l,r):
    if l<r:
        q = partition(array,l,r)
        quickSort(array,l,q-1)
        quickSort(array,q+1,r)
def partition(array,l,r):
    x = array[r] #选最后一位作为分割点,大于它的放到右边,小于它的放到左边,快排基本思想
    i = l-1
    for j in range(l,r):
        if array[j]<=x:
            i+=1
            array[i],array[j] = array[j],array[i]
    array[i+1],array[r] = array[r],array[i+1]      #把小于r的数字全部找出来后,数组中有i+1个小于或等于r,array[i+1]大于r,因此把r和i+1交换,大的放后面
    return i+1

写法二

def partition(array,l,r):
    key = array[l]
    while l<r:
        while l<r and array[r]>key:
            r-=1
        array[l] = array[r]
        while l<r and array[l]<=key:
            l+=1
        array[r] = array[l]
    array[l]=key
    return l
def quickSort(array,low,high):
    if low < high:
        q = partition(array,low,high)    
        quickSort(array,low,q-1)
        quickSort(array,q+1,high)

写法三

因为python的列表可以直接用+号把元素添加进去,所以出现了这一种简化写法:

def quickSort(array):
    if len(array) < 2:
        return array
    else:
        pivot = array[0]
        less = [i for i in array[1:] if i <= pivot]
        greater = [j for j in array[1:] if j > pivot]
        return quickSort(less) + [pivot] + quickSort(greater)

时间复杂度: 最好是 O( n log n ) 最坏是O(n2)
稳定性:不稳定
缺点: 由于每次都需要和中轴元素交换,因此原来的顺序就可能被打乱。如序列为 5 3 3 4 3 8 9 10 11会将3的顺序打乱。所以说,快速排序是不稳定的!基本有序时,退化为冒泡排序,几乎要比较NN次,故为O(NN)

归并排序

def merge(left,right):
    result = []
    while left and right:
        result.append(left.pop(0) if left[0] <= right[0] else right.pop(0))
    while left:
        result.append(left.pop(0))
    while right:
        result.append(right.pop(0))
    return result

def mergeSort(relist):
    if len(relist) <= 1:
        return relist
    mid_index = len(relist)//2  #直接取整,不然会报错(python3)
    #print(mid_index)
    left = mergeSort(relist[:mid_index])
    right = mergeSort(relist[mid_index:])
    return merge(left,right)

归并的思想就很简单,把数据一分为二,再分为四,即分治法的思想。分开后再根据左右比较大小从而合并。

时间复杂度: 最好最坏都是 O( n log n )
稳定性:稳定
缺点:每次拆分数组都要开心的数组, 每次合并数组都要开新数组,空间复杂度很大,需要O(n)的额外空间

堆排序

def siftup(lst,temp,begin,end):
	if lst == []:
		return []
	i,j = begin,2*begin+1
	while j<end:
		if j+1 < end and lst[j+1] > lst[j]:
			j+=1
		elif temp > lst[j]:
			break
		else:
			lst[i] = lst[j]
			i,j = j, 2*j+1
	lst[i] = temp
def heap_sort(lst):
	if lst==[]:
		return []
	end = len(lst)
	for i in range((end//2)-1,-1,-1):
		siftup(lst,lst[i],i,end)
	for i in range(end-1,0,-1):
		temp = lst[i]
		lst[i] = lst[0]
		siftup(lst,temp,0,i)
	return lst

堆排序的思想就是先构建一个最大堆或最小堆。以最大堆为例,堆顶是最大,最底下的数最小。
建立好初始堆后,把最大堆堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出,这个过程持续到剩余数只有一个时结束。

时间复杂度: 最好和最坏情况下:O(N*logN),因此它是一种效果不错的排序算法。
稳定性:不稳定
缺点:需要一直维护堆

关于各个排序算法的详细解释,可以参考下面的一些链接:

堆排序思路
常见排序算法总结

猜你喜欢

转载自blog.csdn.net/xty5057212/article/details/88865307