在路上---学习篇(一)Python 数据结构和算法 (4) --希尔排序、归并排序
独白:
希尔排序是经过优化的插入排序算法,之前所学的排序在空间上都是使用列表本身。而归并排序是利用增加新的空间,来换取时间复杂度的减少。这俩者理念完全不一样,注定造成的所消耗的时间不同以及空间上的不同。
归并排序涉及到递归的使用,需要理解其中精髓才能更好了解归并排序,以及其他应用到递归的算法。理解其本质才能更好的应用。
希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
时间复杂度
- 最优时间复杂度:根据步长序列的不同而不同
- 最坏时间复杂度:O(n2)
- 稳定想:不稳定
""" 希尔排序 最优时间复杂度: 根据步长序列不同而不同 最坏时间复杂度: O(n*n) 稳定性 : 不稳定 """ import time import random def shell_sort(list): n = len(list) #初始步长 gap = n // 2 while gap > 0: # 按初始步长进行插入排序 for j in range(gap, n): i = j # 插入排序 while i >= gap and list[i-gap] > list[i]: list[i-gap], list[i] = list[i], list[i-gap] i -= gap # 得到新的步长 gap = gap // 2 def new_num(lis): """随机生成50个数加入列表中""" for i in range(50): j = random.randint(0, 10000) lis.append(j) if __name__ == '__main__': first_time = time.time() # 空列表 lis = [54,26,93,17,77,31] # 随机函数添加到列表中 # new_num(lis) print(lis) # 列表排序 shell_sort(lis) print(lis) # 结束时间 last_time = time.time() print("共用时%s" % (last_time - first_time))
归并排序
归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。
将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(nlogn)
- 稳定性:稳定
""" 归并排序 最优时间复杂度:O(nlogn) 最坏时间复杂度:O(nlogn) 稳定性:稳定 与其他排序区别 利用一个新列表讲算法排序后的元素储存当中 空间换时间 """ import time import random def merge_sort(list): """归并排序""" n = len(list) if n <= 1: return list # 最大整除 mid = n // 2 # left 利用递归 截取的列表形成的有序列表 left_list = merge_sort(list[:mid]) # right 利用递归 截取的列表形成的有序列表 right_list =merge_sort(list[mid:]) # 创建 左右游标记录列表值的索引 left_pointer, right_pointer = 0,0 # 创建新空列表 result = [] # 循环 比较数值大小 # 退出循环条件 当左右游标其中一个等于所在列表的长度时 while left_pointer < len(left_list) and right_pointer < len(right_list): # 判断 左值和右值大小 if left_list[left_pointer] <= right_list[right_pointer]: result.append(left_list[left_pointer]) # 每判断一次 游标加一 left_pointer += 1 else: result.append(right_list[right_pointer]) right_pointer += 1 # 将最后一个数值加入新列表中 result += left_list[left_pointer:] result += right_list[right_pointer:] # 返回值 return result def new_num(lis): """随机生成50个数加入列表中""" for i in range(50): j = random.randint(0, 100) lis.append(j) if __name__ == '__main__': first_time = time.time() # 空列表 lis = [] # 随机函数添加到列表中 new_num(lis) print(lis) # 列表排序 # 因为归并排序最后是返回一个新列表,所以打印输出为新列表 alist = merge_sort(lis) print(alist) # 结束时间 last_time = time.time() print("共用时%s" % (last_time - first_time))