概述
插入排序
将未排序的元素同已排序的元素从后往前比较,带排序元素:a,被比较元素:b,如果a<b则, swap(a,)
快速排序
每趟排序把基准值放到对的位置即左边的元素都比它小,右边的元素都比它大
冒泡排序
每一趟排序(包括多次两两比较和交换)找出余下的最大元素放在数组的最后,叫沉底排序更贴切。
选择排序
对未排序的元素找出最小的元素, 放到未排序数组的0号位置
希尔排序
插入排序的改进;插入排序比较移动的步长是1,希尔排序中改进该步长,从大缩小到1
堆排序
利用大顶堆的特点:根的值比左右子树都大
先构造大顶堆
交换堆的第一个元素和最后一个元素,使最大的元素放在数组的最后,再对前面的堆进行调整,重复该操作
归并排序
递归地合并两个有序数组 ,不断一分为二拆分数组,当左右数组长度为1时,开始排序并合并,之后对合并后的数组(已排序)继续归并排序,采用分而治之的思想
1. 冒泡排序
每一趟排序(包括多次两两比较和交换)找出余下的最大元素放在数组的最后,叫沉底排序更贴切
def bubble_sort(nums):
lgh = len(nums)
for i in range(lgh - 1):
for j in range(lgh - i - 1):
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
return nums
2.选择排序
- 时间复杂度 O(n^2),空间复杂度 O(1)
- 对未排序的元素找出最小的元素, 放到未排序数组的0号位置
def selection_sort(nums):
lgh = len(nums)
for i in range(lgh - 1):
for j in range(i + 1, lgh):
if nums[i] > nums[j]:
nums[i], nums[j] = nums[j], nums[i]
return nums
3.插入排序
每一趟排序把本次排序的元素往前插入到合适的位置
def insert_sort(nums):
lgh = len(nums)
# 比较测试 次数
for i in range(1, lgh):
for j in range(i, 0, -1):
# 防止 j-1 <0
if j == 0:
break
if nums[j] < nums[j - 1]:
nums[j], nums[j - 1] = nums[j-1], nums[j]
else:
break
return nums
4.希尔排序
原理
希尔排序,就是按某个增量值对数据进行分组,每组单独排序好后,再缩小这个增量,然后按新增量对数据分组后每个分组再各自排序。最终增加缩小到1的时候,排序结束。所以希尔排序又叫缩小增量排序(Diminishing Increment Sort)
关于增量
最佳增量值的选择其实是个数学难题,有兴趣的可以自己搜下相关资料。
常用的增量有 n/2(这个又叫希尔增量)、n/3、2^k-1(hibbard增量)等,实际使用中稍微改版增量也可能使排序的性能产生很大的波动。
比如使用n/2的增量,就是初始增量就是 length/2 ,第二轮分组时就再除2:length/4,直至增量值变成1
流程
假设有个数组:[8,12,6,33,12,5,4,94,63,23,75,22,43,27,46],以n/2为增量,那么整个排序流程就是这样的:
[golang] 数据结构-希尔排序
复杂度
不同增量复杂度不同。n/2时平均的时间复杂度为O(n^2)。
相较直接插入排序,希尔排序减少了比较和交换的次数,在中小规模的排序中,性能表现较好。但随着数据量增大,希尔排序与其他更好的排序算法(快排、堆排、并归等)仍有较大差距。
作者:holdtom
链接:https://www.imooc.com/article/271234
来源:慕课网基本思想
先将整个待排序的记录序列
分割
成为若干子序列分别进行直接插入排序 待整个序列中的记录“基本有序
”时 再对全体
记录进行依次直接插入排序插入排序的改进;插入排序比较移动的步长是1,希尔排序中改进该步长,从大缩小到1
def shell_sort(nums):
gap = int(len(nums) / 2)
while gap > 0:
insert_sort_step(nums, gap)
gap = int(gap / 2)
return nums
def insert_sort_step(nums, step):
lgh = len(nums)
for i in range(step, lgh):
j = i
while j >= step and nums[j] < nums[j-step]:
nums[j - step], nums[j] = nums[j], nums[j - step]
j -= step
return nums
5.归并排序
不断一分为二拆分数组,当左右数组长度为1时,开始排序并合并,之后对合并后的数组(已排序)继续归并排序,采用分而治之的思想
def merge_sort(nums):
lgh = len(nums)
if lgh < 2:
return nums
middle = int(lgh / 2)
left = merge_sort(nums[:middle])
right = merge_sort(nums[middle:])
return merge(left, right)
def merge(left, right):
nums = []
l, r = 0, 0
while r < len(right) and l < len(left):
if left[l] < right[r]:
nums.append(left[l])
l += 1
else:
nums.append(right[r])
r += 1
if l == len(left):
nums.extend(right[r:])
else:
nums.extend(left[l:])
return nums
6.堆排序
def heapify(arr, n, i):
largest = i
l = 2 * i + 1 # left = 2*i + 1
r = 2 * i + 2 # right = 2*i + 2
if l < n and arr[i] < arr[l]:
largest = l
if r < n and arr[largest] < arr[r]:
largest = r
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i] # 交换
heapify(arr, n, largest)
def heapSort(arr):
n = len(arr)
# Build a maxheap.
for i in range(n, -1, -1):
heapify(arr, n, i)
# 一个个交换元素
for i in range(n - 1, 0, -1):
arr[i], arr[0] = arr[0], arr[i] # 交换
heapify(arr, i, 0)
7.快排
def quick_sort(nums):
lgh = len(nums)
if lgh < 2:
return nums
left = []
right = []
middle = nums[0]
for i in range(1, lgh):
if middle < nums[i]:
right.append(nums[i])
else:
left.append(nums[i])
return quick_sort(left) + [middle] + quick_sort(right)