查找算法
二分查找
import doctest def binary_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 == []: return None elif alist[binary_index] > item: return binary_search(alist[:binary_index], item) elif alist[binary_index] < item: result = binary_search(alist[binary_index + 1:], item) return None if result is None else result + binary_index + 1 elif alist[binary_index] == item: return binary_index if __name__ == "__main__": doctest.testmod(verbose=True)
排序算法
选择排序
原理:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
稳定性:不稳定
最差时间复杂度:O(n^2)
平均时间复杂度:O(n^2)
import doctest
def 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[:] def select_sort_(alist, reverse): if alist == []: return [] item = max(alist) if reverse else min(alist) alist.remove(item) return [item] + select_sort_(alist,reverse) return select_sort_(alist, reverse) if __name__ == "__main__": doctest.testmod(verbose=True)
冒泡排序
原理:依次比较相邻两个元素大小,交换两元素位置使之满足递增或递减关系,完成一次从序列头到序列尾部的过程称为一次冒泡,一次冒泡会产生最大或最小值于队列尾部,下一次冒泡序列长度减1,序列尾部的有序序列长度加1
稳定性:稳定
最差时间复杂度:O(n^2)
平均时间复杂度:O(n^2)
import doctest
def 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] """ def swap(alist, index1, index2): temp = alist[index1] alist[index1] = alist[index2] alist[index2] = temp pass alist = 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) return alist if __name__ == "__main__": doctest.testmod(verbose=True)
插入排序
原理:将序列元素依次插入到序列首部的有序序列中,即每个元素执行一次有序插入操作
稳定性:稳定
最差时间复杂度:O(n2)
平均时间复杂度:O(n2)
import doctest def 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 in result: 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) return result if __name__ == "__main__": doctest.testmod(verbose=True)
快速排序
原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
性质:不稳定
最差时间复杂度:O(n2)
平均时间复杂度:O(nlogn)
import doctest import copy import random def 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) def quick_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 in alist: 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) return quick_sort_(alist, reverse) if __name__ == "__main__": doctest.testmod(verbose=True)
归并排序
原理:将序列通过递归二分拆分到不可分,不可分的序列可以认为是有序序列,然后将两个有序序列合并为一个有序序列,直到整个序列变为一个有序序列
稳定性:稳定
最差时间复杂度:O(nlogn)
平均时间复杂度:O(nlogn)
import doctest def 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] """ def merger(a, b): result = [] for n in range(len(a) + len(b)): if a == []: return result + b elif b == []: return result + a elif (a[0] < b[0] and reverse == False) or (a[0] > b[0] and reverse == True): result += [a.pop(0)] else: result += [b.pop(0)] return result def merger_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) return merger(left_list,right_list) return merger_sort_(alist) if __name__ == "__main__": doctest.testmod(verbose=True)
堆排序
原理:堆排序也是选择排序的一种,他是利用完全二叉树的结构,从而构造出最大堆或最小堆,将堆顶元素替换到堆尾,如此反复,从而构造出有序序列
稳定性:不稳定
最差时间复杂度:O(nlogn)
平均时间复杂度:O(nlogn)
import doctest def 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[:] def perc_down(A, i, N): Ai = A[i] def perc_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] = Ai return temp perc_down_(A, i, N) def swap(A, a, b): temp = A[a] A[a] = A[b] A[b] = temp for 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) return A if __name__ == "__main__": doctest.testmod(verbose=True)