文章目录
前言
可私聊进一千多人Python全栈交流群(手把手教学,问题解答)
进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
- 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!
-
一、排序
排序就是将某个容器中的所有元素按照从小到大或者从大到小的书顺序进行排列。
在现实生活中我们也是比较常见排序这种操作的,比如学生上体育课,老师要求学生按照身高从高到低的顺序排列。
比如我们在遇到某个问题想要搜索文章的时候,也可以选择怎么排列搜索到的东西,俗称检索,比如按阅读量,热度,发布时间等。
之所以要排序就是为了更好的分辨,操作这些数据,让我们更直观的感受到数据整体。
排序是将一组
无序
的记录排列调整为有序
的记录序列当然排序分为升序和降序。
Python内置排序函数sorted(列表/字典等),列表内置排序函数:列表.sort()
二、列表排序
Python中比较常用的列表(也可以当其他语言的数组用,只不过列表可以容纳所有元素,也可以混搭),就是通过一些办法将无序列表变为有序列表。
伪代码:
def 排序名(列表):
排序
return 列表
那么排序的方法有很多种,相信大家都听说过十大排序法。
十大排序法包括:冒泡排序,选择排序,插入排序,快速排序,堆排序,归并排序,希尔排序,桶排序,基数排序,计数排序。
三、冒泡排序(Bubble Sort)
冒泡排序作为学习排序的人第一个学习的排序方式,相比很多人都对他很熟悉
3.1 冒泡排序思想
冒泡排序就像名字一样,跟冒泡一样。那么冒泡排序的是什么样的思想呢?
通过嵌套循环遍历两次列表,将相邻元素进行对比(按照从小到大排序),如果左边大(下标小的大),就互换位置,简而言之,每一次内部循环就是将大的向列表尾部移动。
内循环完毕后,列表中最大的元素必定是处于列表的最后面的,如果是从大到小的排序,那么最后面的就是最小的元素
是不是看着有点蒙蒙的,没事, 上图。
3.2 冒牌排序代码实现
升序版:
def bubble_sort(li:list)->list: for i in range(len(li)): # 外循环 for j in range(len(li)): # 内循环 if i==j: # 跳过相同元素比较 continue if li[i] < li[j]: # 比较相邻元素,符合条件交换 temp = li[j] # 交换 li[j] = li[i] li[i] = temp return li # 返回不返回都行,因为是直接操作下标交换的 li = [3, 1, 6, 8, 5] bubble_sort(li) print(li)
运行结果:
降序版只需要将比较条件的
<
换成>
就行了。优化版:
def bubble_sort(li:list)->list: for i in range(len(li)-1): # 外循环 for j in range(len(li)-i-1): # 内循环 # if i==j: # 跳过相同元素比较 # continue if li[j] > li[j+1]: # 比较相邻元素,符合条件交换 li[j],li[j+1] = li[j+1],li[j] #return li # 返回不返回都行,因为是直接操作下标交换的 li = [3, 1, 6, 8, 5] bubble_sort(li) print(li)
3.3 冒牌排序复杂度分析
时间复杂度就是
O($x^2$)
空间复杂度就是
O(1)
(因为无序列表是题目给的,我们没有新建一个新的列表,所以是这个)四、选择排序(Select Sort)
选择排序就是从无序列表中选择出一个最小/最大值,然后将他放在一个位置(列表最前面,或者最后面),同样的是双重循环。
这个听起来是不是蛮简单的,其实也确实挺简单的。我就不画图了。
4.1 选择排序思想
通过双层循环
内循环每次遍历找出未被排序的最小值
与列表首个元素进行交换,最小值被安排在下标为0的位置
下次循环跳过已被找出的
外循环结束排序完毕
4.2 选择排序代码
def select_sort(li): for i in range(len(li)-1): # 外部循环,最后一个没必要了,因为肯定是最大值了 min_num_index = i # 设置最小元素的下标默认值,用于列表元素交换 for j in range(i, len(li)): # 内部循环,从i开始是因为要跳过已经找到的最小元素 if li[j] < li[min_num_index]: # 条件判断 min_num_index = j # 最小值下标 li[min_num_index],li[i] = li[i],li[min_num_index] # 交换操作 li = [2, 5, 3, 6, 1, 8, 0] select_sort(li) print(li)
4.3 选择排序复杂度分析
时间复杂度就是
O($x^2$)
空间复杂度就是
O(1)
五、插入排序(Insert Sort)
就是先找一个锚点,比如下标为0的元素,然后将后面的元素挨个插进0的左右,插入排序就是这么一个过程。
如果不好理解的话,那么我讲个例子:
我在打斗地主,我们这有个玩法叫盲牌,就是分好底牌,然后算每个人几张,不看牌全发完,玩家不能看牌,选择是否要地主
那么我们整理牌的过程,就是插入排序的过程。
我们把我们的牌看做一个列表,我们从最上面的开始起牌,然后我们把起的牌按照顺序装好,就是插入排序
5.1 插入排序思想
以第一个元素为手牌,然后起牌,按照顺序插入手牌,牌起完,就是排序完毕的时候。
5.2 插入排序代码
说着简单,那么代码怎么写呢?
def insert_sort(li): for i in range(1,len(li)): #从底牌区摸牌,第一张牌跳过,不需要整理 j = i-1 # 左手持的牌数的最大下标 temp = li[i]# 右手摸牌准备入手的牌 while li[j] > temp and j>=0: # 整理手牌区,从后往前与手牌区的牌进行比较 li[j+1] = li[j] # 将符合条件的手牌往后移动 j -= 1 # 当准备入手的牌比手牌区的某个牌小,终止循环,将牌插入 li[j+1] = temp # 插入底牌,成为手牌 如果手牌区全部不符合条件,j此时为-1
这个代码是值得思考的,while循环的目的就是把你摸得牌与手牌最后一个进行比较,然后比摸牌大的话,就将手牌右移,小于停止循环,将摸的牌插入到手牌区,如果都大于,那j会减小到-1,将牌直接插入手牌区最左边即可。
运行结果:
将每次插入的列表打印出来,方便理解
5.3 复杂度分析
时间复杂度就是
O($x^2$)
空间复杂度就是
O(1)
结语
为什么十大排序法只说了这三个呢?因为这三个是十大排序法里时间复杂度最高的,都是
O($x^2$)
。不止算法需要多练,学习任何一门编程语言都是需要多加练习的,纸上学来终觉浅,须知此事要躬行!