排序是必须掌握的基本算法,在面试题也经常考到,这里写一下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),因此它是一种效果不错的排序算法。
稳定性:不稳定
缺点:需要一直维护堆
关于各个排序算法的详细解释,可以参考下面的一些链接:
堆排序思路
常见排序算法总结