一.冒泡排序:
1.原理:
相邻运算两两相比较,将大的向后移,第一轮全部两两比较完毕后,最大值就在最大索引处。依此类推,每轮都会找到一个"最大值",并将其置于当前轮次的最后位置,直到结束。
2.具体思路:
以下述列表为例:
3 | 5 | 4 | 7 | 2 |
第一轮:
第一次比较:位于 0 索引的数字 3,将与位于 1 索引的数字 5 进行比较,数字 5 比数字 3 大,因此数字 3 和数字 5 的位置不需要改变。
第二次比较:位于 1 索引的数字 5 和位于 2 索引的数字 4 进行比较,数字 5 比数字 4 大,因此将数字 5 与数字 4 的位置互换。
......
以此类推,第一轮结束后的列表结果为:
3 | 4 | 5 | 2 | 7 |
接下来每一轮的思路都和第一轮的思路一样,可以得出以下规律:
比较的总轮数为 列表的长度 - 1。
每一次比较都是 j 和 j + 1 索引位置的元素比较。
每一轮比较的总次数为 列表的长度 - 1 - 轮数(从0开始计数)。
3.Python代码实现:
# 定义冒泡排序的函数
def bubble_sort(my_list):
# 获取列表的长度
n = len(my_list)
# 定义外循环,表示:比较的总轮数
for i in range(n - 1):
# 定义内循环,表示:每轮比较的总次数
for j in range(n - 1 - i):
# 将 j 和 j + 1 索引位置的元素进行比较
if my_list[j] > my_list[j + 1]:
# 进入了if判断,说明索引 j 位置的元素大于 j + 1 位置的元素,将两个元素互换位置
my_list[j + 1], my_list[j] = my_list[j], my_list[j + 1]
# 测试
if __name__ == '__main__':
# 定义初始列表
my_list = [3, 5, 4, 7, 2]
# 调用冒泡排序函数
bubble_sort(my_list)
# 打印排序后的结果
print(f'排序后:{my_list}')
4.对宝宝们的小提示Tips:
1):冒泡排序为 稳定排序算法(因为排序后,相同元素的相对位置不变)。
2):冒泡排序的时间复杂度(最坏)为 O(n^2)。
二.选择排序:
1.原理:
假设索引为 0 的元素为最小值,将其与后续的元素进行比较,找到这些元素真正的最小值,将这个真正的最小值放在索引为 0 的位置上;再从索引为 1 的元素开始,将其与后续的元素进行比较,找到这些元素真正的最小值,将这个真正的最小值放在索引为 1 的位置上;以此类推,直到所有元素排序成功。
一句话概括:依次从列表中选择最小值,放到最小索引处。
2.具体思路:
以下述列表为例:
3 | 5 | 4 | 7 | 2 |
第一轮:
假设此时最小值索引为 0,将位于 0 索引的数字 3 和后续的数字依次进行比较,在 [3,5,4,7,2] 中,最小值为 2;将最小值 2 放到起始位置,即将最小值 2 的索引和索引 0 互换。
第一轮结束后的列表结果为:
2 | 5 | 4 | 7 | 3 |
第二轮:
将位于 1 索引的数字 5 和后续的数字依次进行比较,在剩余未排序的序列 [5,4,7,3] 中,最小值为 3;将最小值 3 放到剩余未排序序列起始位置,即将最小值 3 的索引和索引 1 互换。
第二轮结束后的列表结果为:
2 | 3 | 4 | 7 | 5 |
......
接下来每一轮的思路都和前两轮的思路一样,可以得出以下规律:
比较的总轮数为 列表的长度 - 1。
每一轮都是 i 和 真正最小值索引位置 的元素进行交换。
每一轮比较的总次数为 i + 1 到 列表的最后的一个元素。
3.Python代码实现:
# 定义选择排序函数
def select_sort(my_list):
# 获取列表的长度
n = len(my_list)
# 定义外循环,表示:比较的轮数
for i in range(n - 1):
# 定义用于记录最小值的索引变量 min_index
min_index = i
# 定义内循环,表示:每轮比较的总次数
for j in range(i + 1, n):
# 将 j 和 min_index 索引位置的元素进行比较
if my_list[j] < my_list[min_index]:
# 进入了if判断,说明索引 j 位置的元素小于索引 min_index 位置的元素,将两个索引进行互换
min_index = j
# 走到这里,说明 min_index记录的就是:本轮的最小值
my_list[min_index], my_list[i] = my_list[i], my_list[min_index]
# 测试
if __name__ == '__main__':
# 定义原始列表
my_list = [3, 5, 4, 7, 2]
# 调用选择排序函数
select_sort(my_list)
# 打印排序后的结果
print(f'排序后:{my_list}')
4.对宝宝们的小提示Tips:
1):选择排序为 不稳定排序算法(因为排序后,相同元素的相对位置发生了改变)。
2):选择排序的时间复杂度(最坏)为 O(n^2)。
三.插入排序:
1.原理:
把要排序的列表分为两个部分,左面为排好序的列表,右面是待排序的列表,然后从待排序的列表中依次拿元素,在已排序列表中从后向前扫描,找到相应位置并插入。
2.具体思路:
以下述列表为例:
3 | 5 | 4 | 7 | 2 |
第一轮:
想象将列表分为两部分,即 [3] 和 [5,4,7,2],将未排序列表中的第一个元素5与排好序列表中的3进行比较,数字5大于数字3,所以两个元素的相对位置保持不变,将5插入到3的后面,列表的两个部分变为 [3,5] 和 [4,7,2]。
第一轮结束后的列表结果为:
3 | 5 | 4 | 7 | 2 |
第二轮:
由第一轮推理过程得知,目前列表的两个部分变为 [3,5] 和 [4,7,2],接下来,将未排序列表中的第一个元素 4 与排好序列表中的 5 进行比较,4 比 5 小,因此将 4 插入到 5 的前面;然后 4 继续和前面的 3 进行比较,4 比 3 大,所以 4 保持在当前位置;列表的两个部分变为 [3,4,5] 和 [7,2]。
第二轮结束后的列表结果为:
3 | 4 | 5 | 7 | 2 |
......
接下来每一轮的思路都和前两轮的思路一样,可以得出以下规律:
比较的总轮数为 列表的长度 - 1。
每一轮都是 i 和 j 的每个值 进行比较。
第一轮比较的总次数为 i ~ 0。
3.Python代码实现:
# 定义插入排序的函数
def insert_sort(my_list):
# 获取列表的长度
n = len(my_list)
# 定义外循环,表示:比较的轮数
for i in range(1, n):
# 定义内循环,表示:每轮比较的总次数
for j in range(i, 0, -1):
# 获取当前的元素(待比较的元素),和它前边所有的元素(排好序的元素)依次比较
if my_list[j] < my_list[j - 1]:
# 如果后边的元素比前边的小,就交换
my_list[j], my_list[j - 1] = my_list[j - 1], my_list[j]
else:
# 后边的元素比前边的大,就结束
break
# 测试
if __name__ == '__main__':
# 定义初始列表
my_list = [3, 5, 4, 7, 2]
# 调用插入排序函数
insert_sort(my_list)
# 打印排序后的结果
print(f'排序后: {my_list}')
4.对宝宝们的小提示Tips:
1):插入排序为 稳定排序算法(因为排序后,相同元素的相对位置不变)。
2):插入排序的时间复杂度(最坏)为 O(n^2)。