1.插入排序:将一个记录数据正确插入到已经排好序的有序表部分中
def insertion_sort(sort_array): for i in range(1, len(sort_array)): temp_value = sort_array[i] j = i - 1 while j >= 0 and sort_array[j] > temp_value: sort_array[j+1] = sort_array[j] j -= 1 sort_array[j+1] = temp_value return sort_array if __name__ == '__main__': sort_array = [5, 2, 4, 6, 1, 3, 9, 8] arr = insertion_sort(sort_array) print(arr)
def insertion_sort(sort_array): #发起一个索引1开始的循环来遍历数组。变量array_index是当前索引 for array_index in range(1,len(sort_array)): #arrar_position将从当前索引递减 array_position = array_index #用临时变量temporary_value保存当前索引所指的值,将填充空隙位置 temporary_value = sort_array[array_index] #空隙到达数组最左端或遇到比临时变量小的值就结束平移阶段 while array_position > 0 and sort_array[array_position-1] > temporary_value: #遇到比临时变量小的值就往右平移 sort_array[array_position] = sort_array[array_position-1] #继续检查新position左侧的值 array_position = array_position - 1 #将temporary_value放回到数组的空隙中 sort_array[array_position] = temporary_value #返回已排好序的数组 return sort_array if __name__ == '__main__': sort_array = [3, 4, 65, 25, 45, 15, 13, 16, 32, 63, 89, 99, 125, 87, 62, 41] sorted_array = insertion_sort(sort_array) print(sorted_array)
插入排序最佳情况的运行时间:T(n) = an + b 为n的线性函数
这种情况是因为输入数组已经排好序,如[1,2,3,4,5,6,7],当前元素永远比上一个元素大,while循环下的子句不会被执行
插入排序最坏情况的运行时间: T(n) = an2 + bn + c 为n的二次函数
这种情况是因为输入数组完全倒序,如[7,6,5,4,3,2,1],当前元素永远比上一个元素小,计算机必须将当前元素与整个已排好序的数组部分中的每个元素进行比较
2.归并排序:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些问题,然后再合并这些子问题的解来建立原问题的解
import math # 将两个有序列表归并并成一个有序列表 def Merge(sort_arr, start_value, middle_value, end_value): #定义两个列表 list_01 = [] list_02 = [] # 计算list_01,list_02的长度 num_01 = middle_value - start_value + 1 num_02 = end_value - middle_value # 将sort_arr的数据复制到list_01,list_02 for i in range(num_01): list_01.append(sort_arr[i+start_value]) for j in range(num_02): list_02.append(sort_arr[j+middle_value+1]) # list_01,list_02末尾声明哨兵,用于检查list_01,list_02是否还有未排序的元素 list_01.append(float('inf')) list_02.append(float('inf')) init_01 = 0 init_02 = 0 # 每次迭代找到list_01,list_02两列表中最小的元素复制回列表sort_arr for k in range(start_value, end_value+1): if list_01[init_01] <= list_02[init_02]: sort_arr[k] = list_01[init_01] init_01 += 1 elif list_01[init_01] > list_02[init_02]: sort_arr[k] = list_02[init_02] init_02 += 1 return sort_arr def Merge_sort(sort_arr, start_value, end_value): if start_value < end_value: # 获取中间索引 middle_value = math.floor((start_value + end_value)/2) # 递归分解左半部分 Merge_sort(sort_arr, start_value, middle_value) # 递归分解右半部分 Merge_sort(sort_arr, middle_value+1, end_value) # 归并成原问题排序 Merge(sort_arr, start_value, middle_value, end_value) return sort_arr if __name__ == '__main__': sort_arr = [22, 55, 66, 2, 4, 5, 7, 1, 2, 3, 6, 44, 66, 22, 55, 66, 2, 4, 5, 7, 1, 2, 3, 6, 44, 66] arr = Merge_sort(sort_arr, 0, len(sort_arr)-1) print(arr)
归并排序运行时间:
c n=1
T(n)={
2T(n/2) + cn n>1
n为输入规模(列表中的元素数量)
第一层是树根:只有一个结点,每个结点的代价cn,总代价cn
第二层递归中: 有两个结点,每个结点的代价cn/2,总代价cn
...
第i层递归中:有2i-1个结点,每个结点的代价c(n/2i-1),总代价cn
为了求归并排序的总代价,我们只要把各层的代价加起来即可,递归树具有log2n+1层,每层的代价为cn,所以求归并排序的总代价为cn(log2n+1) = cnlog2n+cn,忽略低阶项和常量c便给出了期望的结果Θ(nlog2n)