其实写代码久了,很容易陷入业务代码的怪圈,什么怪圈呢?就是熟悉的业务能很快上手,可是上限要提高却很吃力,其实这都是缺少了‘内功’的基础导致的。
很多程序员肯定听过这句话:程序=算法+数据
今天主要用python来回顾一下,当初大家入门啃算法时的三大排序,虽然时间复杂度不咋的,也没有快排、堆排那么常见,但是能否灵活其思想却是以后提升上限的一个试金石。
冒泡排序
其实冒泡很好理解,好比有一组列表[3、2、4、6、5、1],从第一组相邻两位数开始比较,也就是3和2,把小的元素排前面,也就是3和2对调,然后继续和第三个数‘4’进行比较,也就是3和4,发现4本来比3大,不需要对调,然后继续比较,直到排成升序为止。
代码实现如下:
def bubble_sort(li):
for i in range(len(li)-1):
for j in range(len(li)-i-1):
if li[j] > li[j+1]:
li[j],li[j+1] = li[j+1],li[j]
当然,还可以优化,比如遇到不需要对调的情况可以跳过遍历等操作,这里主要体现其排序思想。
选择排序
在一组数据里,第一趟遍历找到最小的数,然后放到第一位,然后继续遍历第二小的数,放到第二位,以此类推,完成一组数据的升序排序。
def select_sort(li):
for i in range(len(li)-1):
min_loc = i
for j in range(i+1,len(li)):
if li[j] < li[min_loc]:
min_loc = j
li[i],li[min_loc] = li[min_loc],li[i]
插入排序
插入排序相比前两个就比较难理解,尤其在代码实现部分,最容易出错的是数据的下标容易混乱。整体思路是,随机提取一个数n出来,然后遍历整组数据,把比n小的放左边,比n大的放右边,放置完成之后,继续拿随机一个数出来再重复上述步骤,直到排序完成。
def insert_sort(li):
for i in range(1,len(li)): #把整个数组分为有序区和无序区,默认第0个数是有序的,所以从第1个数到最后一个数为无序区
#[1,4,2,6,7,5]
tmp = li[i] #先把无序区中任意一个数提出来用变量保存
#tmp = 2
j = i-1 #把有序区里的最后一个数的下标提取出来
#j = 1(也就是'4'对应的下标)
while j >=0 and li[j] > tmp: #当有序区的下标不是比0小的时候,说明有序区有数字,并且无序区提取的数字比有序区最后一个数据大的时候,说明此时顺序是乱的
li[j+1] = li[j] #把有序区里的最后一个数和它之后一个数赋值成一样
#[1,4,4,6,7,5](此时j的下标仍然没变,还是代表'4')
j = j-1 #然后把有序区的下标减1,空出位置
#[1, ,4,6,7,5](此时的j又回到了‘1’,相当于第二个4位置暂时是空的)
li[j+1] = tmp #把提取的数字插到空位里面
#[1,2,4,6,7,5]
其实相比快排、堆排来说,这三种算是基本入门了,工作中其实基本用不到,主要是业务上其实很多逻辑实现都有框架帮我们大包大揽,导致一些底层实现的思想被业务覆盖掉了。
注意:
如果对三种排序还是有不懂的,可以去我的github上把测试代码下到本地慢慢理解,里面每个排序的每一行代码都备注了原理,还写好了测试数据以供测试,欢迎点击:ChrisLee的github