目录
1.选择排序
2.冒泡排序
3.插入排序
4.希尔排序
5.快速排序
6.归并排序
7.堆排序
8.基数排序
1.选择排序
算法原理
选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。
原理图:
代码如下:
#选择排序
arr = [4,2,6,5,7,8]
for i in range(0,len(arr)):
for j in range(i+1,len(arr)):
if arr[i] >= arr[j]:
arr[i],arr[j]=arr[j],arr[i]
print(arr)
2.冒泡排序
算法原理
- 比较相邻的元素,如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
原理图:
代码如下:
#冒泡排序
arr = [4,2,6,5,7,8]
for i in range(0,len(arr)-1):
for j in range(0,len(arr)-1-i):
if arr[j] >= arr[j+1]:
arr[j],arr[j+1]=arr[j+1],arr[j]
print(arr)
3.插入排序
算法原理
- 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
- 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面)
原理图
代码如下:
#插入排序
arr = [4,2,6,5,7,8]
for i in range(1,len(arr)):
for j in range(i,0,-1):
if arr[j] <= arr[j-1]:
arr[j],arr[j-1]=arr[j-1],arr[j]
print(arr)
4.希尔排序
算法原理
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
- 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
原理图
代码如下:
defshell_sort(nums):
n = len(nums)
gap = n // 2# 定义增量
# gap等于1的时候相当于最后一步是一插入排序
whilegap >= 1:
forj inrange(gap, n):
i = j
# 增量的插入排序版本
while(i-gap) >= 0:
ifnums[i] < nums[i-gap]:
nums[i], nums[i-gap] = nums[i-gap], nums[i]
i -= gap
else:
break
gap //= 2
returnnums
s = [ 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
print(shell_sort(s))
5.快速排序
算法原理
- 从数列中挑出一个元素,称为 "基准"(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
原理图
代码如下:
defquick_sort(arr, left=None, right=None):
left = 0ifnotisinstance(left,(int, float)) elseleft
right = len(arr) - 1ifnotisinstance(right,(int, float)) elseright
ifleft < right:
partitionIndex = partition(arr, left, right)
quick_sort(arr, left, partitionIndex - 1)
quick_sort(arr, partitionIndex + 1, right)
returnarr
defpartition(arr, left, right):
pivot = left
index = pivot+ 1
i = index
whilei <= right:
ifarr[i] < arr[pivot]:
swap(arr, i, index)
index += 1
i+= 1
swap(arr, pivot, index - 1)
returnindex - 1
defswap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
s = [ 3, 15, 36, 26, 27, 2,5, 4, 19, 2, 48]
print(quick_sort(s))
6.归并排序
算法原理
- 开辟内存空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
- 重复步骤 3 直到某一指针达到序列尾;
- 将另一序列剩下的所有元素直接复制到合并序列尾。
原理图
代码如下:
frommath importfloor
defmerge_sort(arr):
if(len(arr) < 2):
returnarr
# 二分
middle = floor(len(arr) / 2)
left, right = arr[ 0:middle], arr[middle:]
# 递归
returnmerge(merge_sort(left), merge_sort(right))
defmerge(left, right):
result = []
# 分治
whileleft andright:
ifleft[ 0] <= right[ 0]:
result.append(left.pop( 0))
else:
result.append(right.pop( 0))
whileleft:
result.append(left.pop( 0))
whileright:
result.append(right.pop( 0))
returnresult
s = [ 3,9, 26, 27, 2, 5, 4, 19, 8 48]
print(merge_sort(s))
7.堆排序
算法原理
- 将待排序序列构建成一个堆 H[0……n-1],根据(升序降序需求)选择大顶堆或小顶堆;
- 把堆首(最大值)和堆尾互换;
- 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
- 重复步骤 2,直到堆的尺寸为1。
frommath importfloor
defbuildMaxHeap(arr):
fori inrange(floor(len(arr) / 2), -1, -1):
heapify(arr, i)
defheapify(arr, i):
left = 2* i + 1
right = 2* i + 2
largest = i
ifleft < arrLen andarr[left] > arr[largest]:
largest = left
ifright < arrLen andarr[right] > arr[largest]:
largest = right
iflargest != i:
swap(arr, i, largest)
heapify(arr, largest)
defswap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
defheap_sort(arr):
globalarrLen
arrLen = len(arr)
buildMaxHeap(arr)
fori inrange(len(arr) -1, 0, -1):
swap(arr, 0, i)
arrLen -= 1
heapify(arr, 0)
returnarr
s = [ 3,26, 27, 2, 46, 4, 19, 44, 33]
print(heap_sort(s))
代码如下:
8.基数排序
算法原理
- 取得数组中的最大数,并获取其位数;
- arr为原始数组,从最低位开始取每个位组成 radix 数组;
- 对 radix 进行计数排序(利用计数排序适用于小范围数的特点);
原理图
代码如下:
defradix_sort(nums):
# 算n:为了计算最高位
max_num = max(nums)
n = 1
whilemax_num > 10** n:
n += 1
fork inrange(n):
# 初始化0-9个桶来排序
buckets = [[] fori inrange( 10)]
forsubnum innums:
buckets[int(subnum / ( 10** k) % 10)].append(subnum)
nums = [num forbucket inbuckets fornum inbucket]
returnnums
s = [ 3, 10, 36, 26, 27, 2,44, 4, 19, 50, 33]
print(radix_sort(s))