python算法【】
冒泡
思想:每次比较相邻的两个值,将最大的值(升序)或最小(降序)的推向最前面
最终效果:把当前序列的最大值交换到最后一个位置
- 最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
- 最坏时间复杂度:O(n**2)
- 稳定性:稳定
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def bubble(alist): 2 a_len = len(alist) 3 4 for i in range(a_len-1, 0, -1): 5 middle = True 6 for j in range(0, i): 7 if alist[j] > alist[j+1]: 8 alist[j+1], alist[j] = alist[j], alist[j+1] 9 middle = False 10 if middle: 11 break 12 13 14 def main(): 15 alist = [1, 65, 33, 86, 13, 13, 45, 28, 55] 16 print('排序前{}'.format(alist)) 17 bubble(alist) 18 print('排序后{}'.format(alist)) 19 20 21 if __name__ == "__main__": 22 main()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def bubble(alist): 2 a_len = len(alist) 3 4 for i in range(a_len-1): 5 middle = True 6 for j in range(0, a_len-i-1): 7 if alist[j] > alist[j+1]: 8 alist[j], alist[j+1] = alist[j+1], alist[j] 9 middle = False 10 if middle: 11 break 12 13 14 def main(): 15 alist = [1, 65, 33, 86, 13, 13, 45, 28, 55] 16 print('排序前{}'.format(alist)) 17 bubble(alist) 18 print('排序后{}'.format(alist)) 19 20 21 if __name__ == "__main__": 22 main()
选择
思想:在没有排序的序列中找到最小的元素,然后放到序列的起始位置
核心理解:选择当前序列的最小值置于第一个位置,用一个元素和序列后面所有元素进行比较小的置于一个位置
最差时间复杂度: (n-1)+(n-2).......1 ((n-1)+1)//2 * (n-1) 时间复杂度为:O(n**2)
最优时间复杂度 O(n**2)
稳定性:不稳定
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def select_sort(alist): 2 a_len = len(alist) 3 4 for i in range(a_len-1): 5 middle = i 6 for j in range(i+1, a_len): 7 if alist[j] < alist[middle]: 8 middle = j 9 if i != middle: 10 alist[i], alist[middle] = alist[middle], alist[i] 11 12 13 def main(): 14 alist = [1, 65, 33, 86, 13, 13, 45, 28, 55] 15 print('排序前{}'.format(alist)) 16 select_sort(alist) 17 print('排序后{}'.format(alist)) 18 19 20 if __name__ == "__main__": 21 main()
插入
思想:把序列看成两部分,一部分是有序一部分是无序 最开始,把序列的第一个元素看做有序序列
关键点:如何插入到前面的有序序列中,从无序列表中取一个数据依次向前和有序序列的元素比较,如果小则向前
最差时间复杂度: (n-1)+(n-2).......1 ((n-1)+1)//2 * (n-1) 时间复杂度为:O(n**2)
最优时间复杂度:O(n)
稳定性:稳定
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def insert_sort(alist): a_len = len(alist) for i in range(a_len): for j in range(i, 0, -1): if alist[j] < alist[j-1]: alist[j], alist[j-1] = alist[j-1], alist[j] else: break def main(): alist = [1, 65, 33, 86, 13, 13, 45, 28, 55] print('排序前{}'.format(alist)) insert_sort(alist) print('排序后{}'.format(alist)) if __name__ == "__main__": main()
希尔
思想:把整个序列取一个缝隙 gap取一个数据,最终整个序列分成gap个子序列,分别对每个子序列进行插入排序 不断将gap值除二 直到为1时暂停
最差时间复杂度: (n-1)+(n-2).......1 ((n-1)+1)//2 * (n-1) 时间复杂度为:O(n**2)
最优时间复杂度:跟gap取值有关系 O(n^1.3)
稳定性:不稳定
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def shell_sort(alist): # 遍历步长对应元素之后的所有元素,,对每个元素之前的序列进行排序(注意比较元素不是前一个,而是当前元素减去gap值) # 取一个gap值,,为步长,将序列分成gap份,然后对每个序列进行插入排序 a_len = len(alist) gap = a_len // 2 while gap > 0: for i in range(gap, a_len): j = i while j >= gap and alist[j] < alist[j-gap]: alist[j], alist[j-gap] = alist[j-gap], alist[j] j -= gap gap //= 2 def main(): alist = [1, 65, 33, 86, 13, 13, 45, 28, 55] print('排序前{}'.format(alist)) shell_sort(alist) print('排序后{}'.format(alist)) pass if __name__ == "__main__": main() if __name__ == "__main__": main()
快速排序
代码及思想:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def query_sort(alist, start=None, end=None): 2 """实现快速排序 3 思想:首先定义一个基准(一般开始为基准),两个游标,(游标为:序列的起始下标和终止下标,)然后 4 拿基准和终止游标对应的值比较: 5 如果终止游标对应的值比基准小则将终止游标对应值赋值给起始下标对应的值 6 然后:移动前面的游标,指向新的值后再与基准对比 7 如果大于基准,将值赋给终止下标对应的值 8 如果 小于基准移动前面的游标 9 如果:后边的值比基准大:则将后面的游标前前移动 10 (以此类推将可以得到基准的准确位置,再以基准的准确位置分成两部分执行以上的操作) 11 注意: 12 排序过程时,序列中有两个索引(除第一次的比较)对应的值为同一个值: 13 当两个游标碰撞时当前位置则为基准的位置 14 所以外循环的停止条件为:当两个游标相遇时停止 15 """ 16 if start is None or end is None: 17 start = 0 18 end = len(alist) - 1 19 20 if start >= end: 21 return 22 23 base_num = alist[start] 24 25 left_index = start 26 right_index = end 27 28 while left_index < right_index: 29 if alist[right_index] < base_num: 30 alist[left_index] = alist[right_index] 31 left_index += 1 32 while left_index < right_index: 33 if alist[left_index] > base_num: 34 alist[right_index] = alist[left_index] 35 right_index -= 1 36 break 37 else: 38 left_index += 1 39 else: 40 right_index -= 1 41 42 alist[left_index] = base_num 43 # 左 44 query_sort(alist, start=start, end=left_index-1) 45 # 右 46 query_sort(alist, start=right_index+1, end=end) 47 48 49 def main(): 50 alist = [37, 65, 33, 86, 13, 13, 45, 12, 28, 55] 51 print('排序前{}'.format(alist)) 52 query_sort(alist) 53 print('排序后{}'.format(alist)) 54 pass 55 56 57 if __name__ == "__main__": 58 main()
稳定性:不稳定
时间复杂度
- 最坏时间复杂度:当为有序序列时为最坏情况 每轮比较n-1次,,比较n轮 O(n**2)
- 最优时间复杂度:每次对半的时候为最优时间复杂度:logn*(n-1)----》O(nlogn)
归并排序
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def guibin_sort(alist): # 判停条件 if len(alist) <= 1: return alist # 将列表分成两半 a_len = len(alist)//2 l_list = guibin_sort(alist[a_len:]) r_list = guibin_sort(alist[:a_len]) # 定义每个列表的起始页 l_index = 0 r_index = 0 # 创建新列表 将元素,添加到列表当中 new_list = [] # 逐个比较两个列表当中值,将较小值添加到列表当中 当有一个列表为空时,将另一个列表与new_list合并即可 while 1: if l_list[l_index] < r_list[r_index]: new_list.append(l_list[l_index]) l_index += 1 else: new_list.append(r_list[r_index]) r_index += 1 if len(l_list[l_index:]) == 0 or len(r_list[r_index:]) == 0: break new_list += l_list[l_index:] new_list += r_list[r_index:] return new_list def main(): alist = [37, 65, 33, 86, 13, 38, 13, 45, 12, 28, 55] print('排序前{}'.format(alist)) print(guibin_sort(alist)) pass if __name__ == "__main__": main()
最优/最差时间复杂度:O(nlogn)
稳定性:向上合并时可以人为的控制
二分查找