冒泡排序
# coding:utf-8 def bubble_sort(alist): """冒泡排序""" nums = len(alist) - 1 # 要执行的次数 while nums: for i in range(nums): if alist[i] > alist[i+1]: alist[i], alist[i+1] = alist[i+1], alist[i] nums -= 1 return alist if __name__ == "__main__": b = bubble_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(b)
另一种方法
# coding:utf-8 def bubble_sort(alist): """冒泡排序""" nums = len(alist) count = 0 # 记录是否有进行数据交换 for j in range(nums-1): # 规定要执行的次数 for i in range(0, nums-1-j): # 规定每次执行比较的个数 if alist[i] > alist[i+1]: alist[i], alist[i+1] = alist[i+1], alist[i] count += 1 if count == 0: # 说明该序列是有序的序列,不必进行后面的比较,直接返回 return alist return alist if __name__ == "__main__": b = bubble_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(b)
时间复杂度
- 最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
- 最坏时间复杂度:O(n2)
- 稳定性:稳定
改进:当传进来的顺序表是有序的时候
# coding:utf-8 def bubble_sort(alist): """冒泡排序""" nums = len(alist) count = 0 # 记录是否有进行数据交换 for j in range(nums-1): # 规定要执行的次数 for i in range(0, nums-1-j): # 规定每次执行比较的个数 if alist[i] > alist[i+1]: alist[i], alist[i+1] = alist[i+1], alist[i] count += 1 if count == 0: # 说明该序列是有序的序列,不必进行后面的比较,直接返回 return alist return alist if __name__ == "__main__": b = bubble_sort([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) print(b)
选择排序
# coding:utf-8 def select_sort(alist): """选择排序""" n = len(alist) for j in range(n-1): # 外层循环代表执行多少次 min_index = j # j: 0 ~ n-2 共n-1个数字 for i in range(j, n): # 内层循环表示每次从哪开始 if alist[min_index] > alist[i]: min_index = i alist[j], alist[min_index] = alist[min_index], alist[j] return alist if __name__ == "__main__": s = select_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(s)
时间复杂度
- 最优时间复杂度:O(n2)
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定(考虑升序每次选择最大的情况)
插入排序
# coding:utf-8 def insert_sort(alist): """插入排序""" n = len(alist) for j in range(1, n): # 右边的部分 for i in range(0, j): # 左边的部分 i=[0 ~ n-1] if alist[i] > alist[j]: alist[i], alist[j] = alist[j], alist[i] return alist if __name__ == "__main__": i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(i)
上面这种是错的,插入排序的思想是右边 无序部分 的值和左边 有序部分 的值的比较,而且是从左边 有序部分 的右边开始。因此应该改成这样:
# coding:utf-8 def insert_sort(alist): """插入排序""" n = len(alist) for j in range(1, n): # 右边的部分 for i in range(j, 0, -1): if alist[i] > alist[j]: alist[i], alist[j] = alist[j], alist[i] return alist if __name__ == "__main__": i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(i)
优化:
# coding:utf-8 def insert_sort(alist): """插入排序""" n = len(alist) for j in range(1, n): # 右边的部分 i = j while i > 0: if alist[i-1] > alist[i]: alist[i-1], alist[i] = alist[i], alist[i-1] i -= 1 else: break return alist if __name__ == "__main__": i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(i)
时间复杂度
- 最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
- 最坏时间复杂度:O(n2)
- 稳定性:稳定
希尔排序
# coding:utf-8 def shell_sort(alist): """希尔排序""" n = len(alist) gap = n//2 # 取对半 while gap > 0: # 插入算法,与普通的插入算法的区别就是步长gap for j in range(gap, n): # j = [gap, gap+1, gap+2, gap+3] i = j while i > 0: if alist[i] < alist[i-gap]: alist[i], alist[i-gap] = alist[i-gap], alist[i] i -= gap else: break # 缩短gap步长 gap //= 2 return alist if __name__ == "__main__": i = shell_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(i)
时间复杂度
- 最优时间复杂度:根据步长序列的不同而不同
- 最坏时间复杂度:O(n2)
- 稳定想:不稳定
快速排序
# coding:utf-8 def quick_sort(alist, first, last): """快速排序""" if first >= last: return mid_value = alist[first] low = first high = last while low < high: while low < high and alist[high] >= mid_value: high -= 1 alist[low] = alist[high] # low 右移 while low < high and alist[low] < mid_value: low += 1 alist[high] = alist[low] # 从循环退出时, low=high alist[low] = mid_value # 对low左边的列表排序 quick_sort(alist, first, low-1) # 对同一个列表的操作,写成这样"quick_sort(alist[:low-1])"相当于传入新的列表 # 对low右边的列表排序 quick_sort(alist, low+1, last) if __name__ == "__main__": li = [1, 3, 7, 2, 8, 9, 4, 5, 0, 6] quick_sort(li, 0, len(li)-1) print(li)
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定
归并排序
# coding:utf-8 def merge_sort(alist): """归并排序""" n = len(alist) if n <=1: return alist min = n//2 # left 采用归并排序后形成的新的有序的列表 left_li = merge_sort(alist[:min]) # right 采用归并排序后形成的新的有序的列表 right_li = merge_sort(alist[min:]) # 将两个有序的子序列合并为一个新的整体 # 左右列表的两个指针 left_pointer, right_pointer = 0, 0 # 存放结果的列表 result = [] while left_pointer < len(left_li) and right_pointer < len(right_li): if left_li[left_pointer] <= right_li[right_pointer]: # 加等于号 = 是为了遇到相等值时,前面的值还是在前面(稳定) result.append(left_li[left_pointer]) left_pointer += 1 # elif left_li[left_pointer] > right_li[right_pointer]: else: result.append(right_li[right_pointer]) right_pointer += 1 # 不管左边还是右边走到头,退出循环,然后把与之对应的那一边的最后一个值加进来 result += left_li[left_pointer:] result += right_li[right_pointer:] return result if __name__ == "__main__": i = merge_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6]) print(i)
易于理解的版本
def merge_sort(alist): if len(alist) <= 1: return alist # 二分分解 num = len(alist)/2 left = merge_sort(alist[:num]) right = merge_sort(alist[num:]) # 合并 return merge(left,right) def merge(left, right): '''合并操作,将两个有序数组left[]和right[]合并成一个大的有序数组''' #left与right的下标指针 l, r = 0, 0 result = [] while l<len(left) and r<len(right): if left[l] < right[r]: result.append(left[l]) l += 1 else: result.append(right[r]) r += 1 result += left[l:] result += right[r:] return result alist = [54,26,93,17,77,31,44,55,20] sorted_alist = mergeSort(alist) print(sorted_alist)
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(nlogn)
- 稳定性:稳定
二分查找
# coding:utf-8 def binary_search(alist, item): """二分查找 递归""" n = len(alist) if n > 0: min = n//2 if item == alist[min]: return True elif item < alist[min]: return binary_search(alist[:min], item) else: return binary_search(alist[min+1:], item) else: return False def binary_search2(alist, item): """二分查找 非递归""" n = len(alist) first = 0 last = n-1 while first <= last: min = (first + last)//2 if item == alist[min]: return True elif item < alist[min]: last = min -1 else: first = min + 1 return False if __name__ == "__main__": print(binary_search([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 5)) print(binary_search([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10)) print(binary_search2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 5)) print(binary_search2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10))
时间复杂度
- 最优时间复杂度:O(1)
- 最坏时间复杂度:O(logn)
二叉树的定义和广度优先遍历和深度优先遍历
# coding:utf-8 class Node(object): """树的节点""" def __init__(self, item): self.elem = item self.lchild = None self.rchild = None class Tree(object): """二叉树""" def __init__(self): self.root = None def add(self, item): """树的插入""" node = Node(item) if self.root is None: self.root = node return queue = [self.root] while queue: cur_node = queue.pop(0) if cur_node.lchild is None: cur_node.lchild = node break else: queue.append(cur_node.lchild) if cur_node.rchild is None: cur_node.rchild = node break else: queue.append(cur_node.rchild) def breadth_travel(self): """广度遍历""" if self.root is None: return queue = [self.root] while queue: cur_node = queue.pop(0) print(cur_node.elem, end=" ") if cur_node.lchild is not None: queue.append(cur_node.lchild) if cur_node.rchild is not None: queue.append(cur_node.rchild) def preorder(self, node): """先序遍历""" if node is None: return print(node.elem, end=" ") self.preorder(node.lchild) self.preorder(node.rchild) def inorder(self, node): """中序遍历""" if node is None: return self.inorder(node.lchild) print(node.elem, end=" ") self.inorder(node.rchild) def postorder(self, node): """后序遍历""" if node is None: return self.postorder(node.lchild) self.postorder(node.rchild) print(node.elem, end=" ") if __name__ == "__main__": tree = Tree() tree.add(0) tree.add(1) tree.add(2) tree.add(3) tree.add(4) tree.add(5) tree.add(6) tree.add(7) tree.add(8) tree.add(9) tree.breadth_travel() print(" ") tree.preorder(tree.root) print(" ") tree.inorder(tree.root) print(" ") tree.postorder(tree.root)