1、冒泡排序
从第一个元素开始,两两比较相邻元素,如果第一个元素比第二个元素大,则交换相邻元素,这样每经过一轮排序,就会有一个元素在最终位置上。
优化:设置一个flag,当在一次遍历中没有元素交换位置,说明列表已经有序。
时间复杂度:最坏:O(n^2), 平均:O(n^2), 最好:O(n)
空间复杂度:O(1)
稳定的排序算法
def bubble_sort(l):
for i in range(len(l)-1): # len(l)-1轮排序,把len(l)-1个元素排在相应位置,最后一个元素也在相应的位置
flag = 1
for j in range(len(l)-i-1):
if l[j+1]
2、选择排序
每轮循环从未排序元素中选择一个最大的,排在列表的最后位置
因为每轮只选择一个元素,所以选择排序没有优化算法,一定会循环n轮,不适合大规模数据
时间复杂度(最差/平均/最优):O(n^2) O(n^2) O(n^2)
空间复杂度 O(1)
不稳定的排序算法
def select_sort(l):
for i in range(len(l)-1):
max_index = 0
for j in range(len(l)-i):
if l[j] > l[max_index]:
max_index = j
l[j], l[max_index] = l[max_index], l[j]
return l
3、插入排序
将列表分为两部分,左边是排序的,右边未排序。对于未排序部分的每个元素,在已排序列表中从后向前扫描,找到相应位置并插入。
时间复杂度(最差/平均/最优):O(n^2) O(n^2) O(n)
空间复杂度:O(1)
稳定的排序算法
def insertion_sort(l):
for i in range(1,len(l)):
temp = l[i]
for j in range(i-1, -1, -1):
if l[j] > l[i]:
l[j+1] = l[j]
else:
l[j+1] = temp
break
return l
4、快速排序
选取第一个元素为划分元素,列表中小于划分元素的数字都被移到左面,大于划分元素的数字都被移到右面,每一轮会将一个元素放到最终位置上。递归对列表左半部分和右半部分快速排序。
时间复杂度(最差/平均/最优):O(n^2) O(nlogn) O(nlogn)
空间复杂度:O(logn)
不稳定的排序算法
def sub_sort(array, low, high):
key = array[low]
key_index = low
low += 1
while low < high:
while low < high and array[high] >= key:
high -= 1
while low array[high]:
array[low], array[high] = array[high], array[low]
if array[key_index] > array[low]:
array[key_index], array[low] = array[low], array[key_index]
return low
def quick_sort1(array,low,high):
if low < high:
key_index = sub_sort(array,low,high)
quick_sort1(array,low,key_index-1)
quick_sort1(array,key_index+1,high)
if __name__ == '__main__':
array = [8,8,10,9,6,4,16,5,13,26,18,2,45,34,23,1,7,3]
quick_sort1(array,0,len(array)-1)
print array
5、归并排序
def merge(left,right):
temp_ans=[]
i,j = 0, 0
while i=len(left):
temp_ans.extend(right[j:])
if j>=len(right):
temp_ans.extend(left[i:])
return temp_ans
def merge_sort(l):
if(len(l)<=1):
return l
else:
low=0
high=len(l)
mid=(low+high)/2
left=merge_sort(l[low:mid])
right=merge_sort(l[mid:high])
return merge(left,right)
l=[69,3,2,45,67,3,2,4,45,63,24,233]
print merge_sort(l)
6、堆排序
第i个元素的孩子是 2*i+1 和 2*i+2,第i个元素的父节点是 (i-1)/2
建堆:构建一个最大堆(父节点的值大于等于左右子节点),从第一个非叶节点开始向下调整,如果该节点小于子节点,交换该节点和子节点的位置,并从该子节点开始递归地向下调整
删除:删除根节点,将最后一个元素插入到根节点,并从根节点开始,递归地向下调整
插入:插入到最后一个位置,从最后一个元素开始,递归地向上调整
时间复杂度:建堆的时间复杂度是 O(n),每次调整堆的时间复杂度是 O(logn) ,需要调整n次,总的时间复杂度为 O(nlogn)
空间复杂度:用列表模拟建堆过程,可以实现原地排序,空间复杂度为O(1)
# 从上到下调整堆, length是需要调整的列表的最后一个元素位置,top是调整的起始位置
def top_down(l, length, top):
while True:
child = 2*top+1
if child > length:
break
if child+1 <= length and l[child] < l[child+1]:
child += 1
if l[child] > l[top]:
l[child], l[top] = l[top], l[child]
top = child
else:
break
def heap_sort(l):
length = len(l)-1
# 构建最大堆,从第一个非叶子节点开始调整
for top in range((length-1)/2, -1, -1):
top_down(l, length, top)
# print l
# 将排序好的元素放到列表最后一个位置上并调整堆
for i in range(length, 0, -1):
l[0], l[i] = l[i], l[0]
top_down(l, i-1, 0)
#print i-1, l
l = [ 1, 2, 3, 3, 5, 12, 11, 13, 5, 6, 7]
heap_sort(l)
print l