算法中最基础的应该就是排序算法了,今天简单介绍一下几种常用的排序算法
冒泡排序
冒泡排序每轮走访一次要排序的元素列表,依次比较两个相邻的元素,如果两个元素顺序不正确的话就将他们交换过来调整好顺序,这样的话每一轮比较的最大的值会浮到最上方,也就是变为最后一个值。按照这样的想法执行的话,相当于每一轮的最后一个元素不需要参与到下一轮的比较(因为已经是最大了)。
python实现:
def bubble_sort(arr):
for i in range(1, len(arr)):
# 这里表示要排序多少次,比如只有两个元素的话肯定只需要排序一次就结束啦,所以从1到元素长度的次数
for j in range(0, len(arr)-i):
# 这里表示对从第一个元素到之后元素的循环,减去i是因为len(arr)-i之后的元素已经被排序好了
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
# 这里的步骤就是在将最大的元素放到当前正在排序的元素的最后一位
#(有一部分已经排好的就不参与排序了)
return arr
选择排序
选择排序的想法是每次都选择最小的值放在最左边,执行len(arr)-1次即可。
python实现:
def selection_sort(arr):
for i in range(len(arr)-1):
min_num_index = i
for j in range(i+1, len(arr)):
if arr[j] < arr[min_num_index]:
min_num_index = j
if i != min_num_index:
arr[i], arr[min_num_index] = arr[min_num_index], arr[i]
return arr
快速排序
快速排序相对会复杂一点,其会设定分界值,通过分界值将数组分为左右两部分,然后继续在每个部分中设定分界值继续分组,直到排序所剩的某个分界值变为空为止。也就是按照这个方法来做的话,就变为了递归的方式了。当然不用递归应该也行,就是写起来会麻烦点。
这里介绍使用递归方式实现快速排序:
def quick_sort(arr):
if arr == []: # 这里是递归的结束条件,其实arr中只有一个元素也可以作为结束条件,
# 但是设置为空更好,因为当arr中如果只有一个元素的话,那么下一次分隔绝对有一边为空
return arr
else:
delimiter = arr[0] # 如果arr非空,指定的分隔数设置为arr第一个元素
left = quick_sort([num for num in arr[1:] if num <= delimiter])
# 小于分隔数的元素全放左边,递归调用本身的方法
right = quick_sort([num for num in arr[1:] if num > delimiter])
# 大于分隔数的元素全放右边,递归调用本身的方法
return left + [delimiter] + right # 最后返回排序好的左边+分隔数+右边
return arr
插入排序
插入排序的想法是每次都让后面的未排序的元素前面已经排序好的元素中插入。
python实现:
def insert_sort(arr):
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]
return arr
归并排序
归并排序相对较为复杂点,其想法是不断的将列表分为两群,然后再不断地对分开后的数据进行合并,合并时每次的两组数据都是有序的,因此很方便排序(就是从两组数据的左边(或右边)每次取一个数据进行比较,哪一边更小(或更大)就被取出来排在新列表中,而那个被取走一个数据的组再取下一个数据和之前剩下的另个组的数据进行比较。这样的排序方式的复杂度是比较小的
)。
python实现:
def delete_first(l):
# 这里我定义了一个函数表示每次删除列表的第一个元素,
# 在python列表中如果有重复元素的话那么使用pop或remove函数会使列表中这个重复值被全删除,
# 所以自己设定了一个函数,每次删除第一个元素
if len(l) == 1:
l= []
else:
l= l[1:]
return l
def merge_sort(arr):
if len(arr) <= 1: # 这里是结束条件
return arr
else:
middle = len(arr)//2 # 从列表中间分隔
left = merge_sort(arr[:middle]) # 同样递归
right = merge_sort(arr[middle:])
arr = [] # 最后的结果存放在这里
while len(left) and len(right): # 如果要对比的两组数据都非空,才继续进行比较
if left[0] >= right[0]: # 如果第一个元素左边大,那么就取右边的第一个元素加到结果中
arr.append(right[0])
right = delete_first(right) # 删除第一个元素(因为已经在结果中了)
else:
arr.append(left[0]) # 同上,只是是右边比较大
left = delete_first(left)
extra = left+right # 由于列表排序可能有一边先排完,因此最后将两表相加
#(这里因为肯定有一边为空,所以直接相加顺序也不会变化,避免了再判断哪一边是有元素的)
for i in extra:
arr.append(i)
# 剩下的元素直接放到结果尾部就可以了(
# 这个理解起来没问题吧,因为剩下的元素就是最大的一些元素,要不然之前就已经被排序了)
return arr
希尔排序
希尔排序的想法是将要排序的元素每次间隔不同的数目进行排序,最开始的时候间隔很大,逐渐减到非常小(当间隔为0时就停下),这里的间隔使用余数的形式来实现,之后每次在之前的余数除以2。希尔排序是插入排序的一种改进方式。
python实现:
def shell_sort(arr):
n = len(arr)
gap = n // 2 # 最开始的间隔
while gap > 0:
for i in range(gap, n): # 插入排序,由于i-gap与i处的值会进行比较,因此从gap开始向后排序即可
while i >= gap and arr[i - gap] > arr[i]: # 这里对选择的每一组数据进行插入排序
arr[i - gap], arr[i] = arr[i], arr[i - gap]
i -= gap # 插入排序的体现(向之前已排序好的数据中插入数据)
gap //= 2 # 慢慢缩小间隔,由于之前已经有一定顺序了,因此之后慢慢排序会较为容易
# 这里的//=符号表示对gap取余数
return arr
叮!
其实除了上面介绍的排序方法,还有其它的一些排序算法,比如基数排序,堆排序等,但是这些相对没有那么常用,再加上自己也没接触到过,这里就不多介绍了。大家感兴趣可以自行去查询一下。
参考:贪心学院机器学习教程: https://www.bilibili.com/video/BV1X34y1S7DW