排序算法-冒泡/插入/归并/希尔排序(python实现)
注意:实现的代码均为对序列的非递减排序操作
1. 冒泡排序
参考博客: https://blog.youkuaiyun.com/guoweimelon/article/details/50902597
核心思想:
(1)遍历N趟排序,每次获取序列中最大或者最小的元素,移动到序列的末端位置
(2)每一趟排序过程都两两比较相邻的元素,将较大/小的元素放置到后一个位置
(3)时间复杂度O(n^2), 空间复杂度O(1)
python实现:
# 冒泡排序
def bubble_sort(input_arr):
input_length = len(input_arr)
for i in range(0, input_length):
for j in range(0, input_length - i - 1):
if input_arr[j] > input_arr[j+1]:
input_arr[j], input_arr[j+1] = input_arr[j+1], input_arr[j]
return input_arr
2. 插入排序
参考博客: https://blog.youkuaiyun.com/guoweimelon/article/details/50904201
核心思想:
(1)遍历N趟排序,每一趟排序过程都将未排序的序列插入到已经排序序列的适当位置
(2)时间复杂度O(n^2), 空间复杂度O(1)
python实现:
# 插入排序
def insert_sort(input_arr):
input_length = len(input_arr)
for i in range(1, input_length):
temp = input_arr[i]
# 此处遍历为查找合适的位置进行插入操作
for j in range(i-1, -1, -1):
if input_arr[j] > temp:
input_arr[j + 1] = input_arr[j]
else:
input_arr[j + 1] = temp
break
return input_arr
3. 折半插入排序
参考博客:https://blog.youkuaiyun.com/guoweimelon/article/details/50904206
核心思想:
(1)遍历N趟排序, 每一趟排序过程都将未排序的序列插入到已经排序序列的适当位置
(2)上述普通插入排序过程中,每次查找适当位置的时候都是直接遍历的,可以尝试使用折半查找的方法进行查找适当的插入位置
(3)时间复杂度O(n^2), 空间复杂度O(1)
python实现:
def binary_insert_sort(input_arr):
input_length = len(input_arr)
for i in range(1, input_length):
temp = input_arr[i]
# 使用二分查找的方法,查找[0, i]之间可以插入元素temp的位置
left = 0
right = i
while left < right:
mid = left + int((right - left) / 2)
if input_arr[mid] >= temp:
right = mid
else:
left = mid + 1
# 查找到合适的位置之后执行插入
for j in range(left, i):
input_arr[j+1] = input_arr[j]
input_arr[left] = temp
return input_arr
4. 归并排序
核心思想:
(1)将待排序序列分成若干子序列,对子序列递归进行归并排序,再将子序列合并成整体有序序列
(2)时间复杂度O(nlogn),空间复杂度O(n)。
归并排序可以自顶向下排序,也可以进行自底向上排序.
自顶向下:从需要归并序列的全部序列出发,依次进行分割:
如对[1,4,5,7,2,6]分割顺序为: (1) [1,4,5],[7,2,6]; (2) [1,4],[5];[7,2],[6]
自底向上:从归并序列的底部出发,即从序列的每一个独立的子序列出发,依次向上归并,如(1) [1,4],[5,7],[2,6]; (2)[1,4,5,7],[2,6]; (3) [1,2, 4,5,6, 7]
https://www.cnblogs.com/agui521/p/6918229.html
自底向上的归并排序对索引值进行操作,故能够很好的对链表数据进行排序.
python实现(自顶向下的归并排序)
# 合并两个有序列表
def merge_list(arr_1, arr_2):
left, right = 0, 0
len_1, len_2 = len(arr_1), len(arr_2)
res = []
# 当第一个有序列表和第二个有序列表都没有遍历结束的时候
while left < len_1 and right < len_2:
if arr_1[left] <= arr_2[right]:
res.append(arr_1[left])
left += 1
else:
res.append(arr_2[right])
right += 1
# 当存在某个列表被遍历结束,则直接将另一个列表的元素插入结果
while left < len_1:
res.append(arr_1[left])
left += 1
while right < len_2:
res.append(arr_2[right])
right += 1
return res
def merge_sort(input_arr):
if len(input_arr) <= 1:
return input_arr
# 拆分列表
mid = int(len(input_arr) / 2)
left = merge_sort(input_arr[0: mid])
right = merge_sort(input_arr[mid:])
return merge_list(left, right)
5. 希尔排序
参考博客: https://blog.youkuaiyun.com/guoweimelon/article/details/50904214
核心思想:
(1) 希尔排序: 对原始序列进行分组排序,插入排序对几乎有序的序列排序时间呈线性的
(2) 核心思想: 先将待排序的序列分割成若干子序列进行插入排序,待整个序列基本有序,再进行整体插入排序;首先要选择一个增量序列d = {n/2 ,n/4, n/8 …1}
python实现:
# 对每个组内的元素进行排序
def gap_sort(arr, start_index, gap_length):
for i in range(start_index + gap_length, len(arr), gap_length):
temp = arr[i]
for j in range(i-gap_length, -1, -gap_length):
if arr[j] > temp:
arr[j + gap_length], arr[j] = arr[j], arr[j + gap_length]
else:
arr[j + gap_length] = temp
break
return arr
def shell_sort(input_arr):
input_length = len(input_arr)
step = 2
# gap表示一个分组内元素的间隔
gap = input_length // step
while gap > 0:
# 对每一组进行排序
for i in range(0, gap):
input_arr = gap_sort(input_arr, i, gap)
# 排序后重新分组
gap = gap // step
return input_arr