查找算法
二分查找
importdoctestdefbinary_search(alist, item):""">>> alist=[1,3,4,7,11,18,29]
>>> binary_search(alist,1)
0
>>> binary_search(alist,7)
3
>>> binary_search(alist,18)
5
>>> binary_search(alist,31)"""binary_index= int(len(alist)/2)if alist ==[]:returnNoneelif alist[binary_index] >item:returnbinary_search(alist[:binary_index], item)elif alist[binary_index]
result= binary_search(alist[binary_index + 1:], item)return None if result is None else result + binary_index + 1
elif alist[binary_index] ==item:returnbinary_indexif __name__ == "__main__":
doctest.testmod(verbose=True)
排序算法
选择排序
原理:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
稳定性:不稳定
最差时间复杂度:O(n^2)
平均时间复杂度:O(n^2)
importdoctestdef select_sort(alist, reverse=False):""">>> alist = [1,7,4,8,6,9,2,5,3]
>>> select_sort(alist)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> select_sort(alist, reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1]"""alist=alist[:]defselect_sort_(alist, reverse):if alist ==[]:return[]
item= max(alist) if reverse elsemin(alist)
alist.remove(item)return [item] +select_sort_(alist,reverse)returnselect_sort_(alist, reverse)if __name__ == "__main__":
doctest.testmod(verbose=True)
冒泡排序
原理:依次比较相邻两个元素大小,交换两元素位置使之满足递增或递减关系,完成一次从序列头到序列尾部的过程称为一次冒泡,一次冒泡会产生最大或最小值于队列尾部,下一次冒泡序列长度减1,序列尾部的有序序列长度加1
稳定性:稳定
最差时间复杂度:O(n^2)
平均时间复杂度:O(n^2)
importdoctestdef bubbing_sort(alist, reverse=False):""">>> alist = [1,7,4,8,6,9,2,5,3]
>>> select_sort(alist)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> select_sort(alist, reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1]"""
defswap(alist, index1, index2):
temp=alist[index1]
alist[index1]=alist[index2]
alist[index2]=temppassalist=alist[:]for cnt in range(len(alist) - 1):for index1 in range(len(alist) - 1 -cnt):
index2= index1 + 1
if (alist[index1] > alist[index2] and reverse == False) or (alist[index1] < alist[index2] and reverse ==True):
swap(alist, index1, index2)returnalistif __name__ == "__main__":
doctest.testmod(verbose=True)
插入排序
原理:将序列元素依次插入到序列首部的有序序列中,即每个元素执行一次有序插入操作
稳定性:稳定
最差时间复杂度:O(n2)
平均时间复杂度:O(n2)
importdoctestdef insert_sort(alist, reverse=False):""">>> alist = [1,7,4,8,6,9,2,5,3]
>>> insert_sort(alist)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> insert_sort(alist, reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1]"""result= alist[:1]for val in alist[1:]:for sort_val inresult:if (val < sort_val and reverse == False) or (val > sort_val and reverse ==True):
result.insert(result.index(sort_val), val)break
else:
result.insert(len(result), val)returnresultif __name__ == "__main__":
doctest.testmod(verbose=True)
快速排序
原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
性质:不稳定
最差时间复杂度:O(n2)
平均时间复杂度:O(nlogn)
importdoctestimportcopyimportrandomdef quick_sort(alist, reverse=False):""">>> alist = [1,7,4,8,6,9,2,5,3]
>>> quick_sort(alist)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> quick_sort(alist, reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1]"""alist=copy.copy(alist)defquick_sort_(alist, reverse):if alist ==[]:return[]
dichotomy_index= random.randint(0, len(alist) - 1)
dichotomy_val=alist[dichotomy_index]
alist.pop(dichotomy_index)
left_list=[]
right_list=[]for val inalist:if (val >= dichotomy_val and reverse == True) or (val < dichotomy_val and reverse ==False):
left_list+=[val]else:
right_list+=[val]return quick_sort_(left_list, reverse) + [dichotomy_val] +quick_sort_(right_list, reverse)returnquick_sort_(alist, reverse)if __name__ == "__main__":
doctest.testmod(verbose=True)
归并排序
原理:将序列通过递归二分拆分到不可分,不可分的序列可以认为是有序序列,然后将两个有序序列合并为一个有序序列,直到整个序列变为一个有序序列
稳定性:稳定
最差时间复杂度:O(nlogn)
平均时间复杂度:O(nlogn)
importdoctestdef merger_sort(alist, reverse=False):""">>> alist = [1,7,4,8,6,9,2,5,3]
>>> merger_sort(alist)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> merger_sort(alist, reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1]"""
defmerger(a, b):
result=[]for n in range(len(a) +len(b)):if a ==[]:return result +belif b ==[]:return result +aelif (a[0] < b[0] and reverse == False) or (a[0] > b[0] and reverse ==True):
result+=[a.pop(0)]else:
result+=[b.pop(0)]returnresultdefmerger_sort_(alist):
contre_index= int(len(alist)/2)
left_list=alist[:contre_index]
right_list=alist[contre_index:]if len(left_list) >= 2:
left_list=merger_sort_(left_list)if len(right_list) >= 2:
right_list=merger_sort_(right_list)returnmerger(left_list,right_list)returnmerger_sort_(alist)if __name__ == "__main__":
doctest.testmod(verbose=True)
堆排序
原理:堆排序也是选择排序的一种,他是利用完全二叉树的结构,从而构造出最大堆或最小堆,将堆顶元素替换到堆尾,如此反复,从而构造出有序序列
稳定性:不稳定
最差时间复杂度:O(nlogn)
平均时间复杂度:O(nlogn)
importdoctestdef heap_sort(alist, reverse=False):""">>> alist = [1,7,4,8,6,9,2,5,3]
>>> heap_sort(alist)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> heap_sort(alist, reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1]"""A=alist[:]defperc_down(A, i, N):
Ai=A[i]defperc_down_(A, i, N):
temp=A[i]
child= i * 2 + 1
if child < N - 1 and ((A[child] < A[child + 1] and reverse == False) or (A[child] >= A[child + 1] and reverse ==True)):
child+= 1
if child < N and ((Ai < A[child] and reverse == False) or (Ai >= A[child] and reverse ==True)):
A[i]=perc_down_(A, child, N)else:
A[i]=Aireturntemp
perc_down_(A, i, N)defswap(A, a, b):
temp=A[a]
A[a]=A[b]
A[b]=tempfor n in list(range(int(len(A)/2)))[::-1]:
perc_down(A, n, len(A))for n in list(range(len(A)))[::-1]:
swap(A, 0, n)
perc_down(A, 0, n)returnAif __name__ == "__main__":
doctest.testmod(verbose=True)