欢迎一起讨论学习(*^__^*) Python技术分享群: 556993881
注!以下的方法实现的都是从小到大排列
1、冒泡排序
释义:
1、假设: 假设第一个数是最大值,
2、依次比较: 将第一个数与后面的每个数进行比较,
3、 替换: 谁大就与"最大值"替换, 继续往后比较,
4、得到最大值:直到比较到最后一个, 将真的最大值放最后
5、缩围重复执行:得到修改一次的序列后,重复1、2、3,比较到倒数第二位即可(倒数第一位已经在上一轮比较过了,是最大的值)此时得到的是较大的值,放在倒数第二位
6、........以此类推,大一点数据像泡泡一样一个接着一个慢慢浮出到后面的位置,得到由大到小的有序序列
# 方法一
def bubble_sort1(li):
n = len(li)
for j in range(n-1): # 遍历n-1次,从0开始
for i in range(n-1-j): # 遍历(n-1)-1次,从下一个开始
if li[i] > li[i+1]: # 比较
li[i], li[i+1] = li[i+1], li[i] # 替换
# 方法二 只是因为内循环用到了外循环的 j ,然后界限做了调整
def bubble_sort2(li):
n = len(li)
for j in range(n-1, 0, -1): # 遍历次数,下标倒着开始
for i in range(j):
if li[i] > li[i+1]:
li[i], li[i+1] = li[i+1], li[i]
# 调用
l = [3, 0, 1, 8, 7, 2, 5, 4, 9, 6]
bubble_sort1(l)
bubble /ˈbʌb(ə)l/ 气泡
最坏时间复杂度:O(n^2) 最优时间复杂度:O(n) (就是一个有序的序列) 稳定
2、选择排序
释义:
1、标记:找个变量记录第一个值的下标
2、遍历比较:从它后面开始遍历到最后一个值,与这第一个值进行比较
3、更改下标:如果出现更小的,就将变量记录更小值的下标
4、替换:一次循环结束将第一个值和下标所在的值进行替换
5、从第二个值开始,继续执行1、2、3、4
6、.......以此类推,直到遍历比较到倒数第二个值
def select_sort(li):
n = len(li)
for j in range(n-1): # 循环n-1次,从0开始
temp = j
for i in range(j+1, n): # 从下一个开始
if li[i] < li[temp]: # 比较
temp = i # 更改标记
li[j], li[temp] = li[temp], li[j] # 替换
# 调用
l = [3, 0, 1, 8, 7, 2, 5, 4, 9, 6]
select_sort(l)
最坏时间复杂度:O(n^2) 最优时间复杂度:O(n^2) 不稳定(假设前后出现两次8,第一个出现的8反而被调整在最后)
3、插入排序
释义:
1、划分有序序列:将第一个元素作为有序的序列看待
2、依次比较: 把后面的一个元素与前面的有序序列中的所有元素依次从后往前进行比较
3、调换位置: 将该元素与比它大的交换,直到找到正确的位置
4、......以此类推,将序列中的所有元素,从左到右全部确定
# 方法一
def insert_sort(li):
n = len(li)
for j in range(n-1):
for i in range(j+1, 0, -1):
if li[i] < li[i-1]:
li[i], li[i-1] = li[i-1], li[i]
# 方法二
def insert_sort(li):
n = len(li)
for j in range(1, n):
for i in range(j, 0, -1):
if li[i] < li[i-1]:
li[i], li[i-1] = li[i-1], li[i]
# 调用
l = [3, 0, 1, 8, 7, 2, 5, 4, 9, 6]
insert_sort(l)
最坏时间复杂度:O(n^2) 最优时间复杂度:O(n) 稳定
4、希尔排序
释义:
1、设定步长:将步长设定为序列长度的一半;
2、比较: 从步长后的元素开始往前(与和自己相差步长的元素)进行比较;
3、交换: 小的在前,大的在后,若再往前移动一个步长还有数值切大于自己那么继续往前比较,直到遇到比自己小或者不存在差 步长的元素;
4、调整步长:步长为上一次步长的一半(也可根据自己喜好划分步长,但最后一定要有一次步长为1的比较,相当于插入排序)
5、3处的交换不好理解,请运行代码,静下心来分析一下
def shell_sort(li):
n = len(li)
gap = n//2 # gap:步长,或者看作∆x
while gap > 0:
for i in range(gap, n): # 步长~最后
# i, i+1 ,i+2
while i-gap >= 0: # 将后面调整的数与前面步长差的数进行调整
if li[i] < li[i - gap]:
li[i], li[i - gap] = li[i - gap], li[i]
i -= gap
else:
break
gap -= 1
# 调用
l = [3, 0, 1, 8, 7, 2, 5, 4, 9, 6]
shell_sort(l)
时间复杂度:O(n) < O < O(n^2), 因为每个人的步长设定不同,认为是对插入排序的优化 不稳定
5、快速排序
释义: 采用一分为二法,或者二分法
1、设定一个中间值:将第一个元素假定为中间值,
2、从列表最后一位开始从右往左的将其他元素与之比较,遇到小的与第一位交换,
3、然后更改方向,从第一位的后一位从左往右的将未比较的元素拿来与之(中间值)比较,遇到大的与 2 中右边被交换的元素进行交换,
4、方向再次改为从右往左, 依次类推,重复2、3,直到所有元素划分完
最终效果是比它小的放左边,比它大的放右边
5、重复1,2,3,4:将左边的一半重复1,2,3,4、,右边的一半也重复1,2,3,4、
6、接着将分得的小序列分支,再进行划分,此处用到了递归(不懂递归,自行补充食粮)
7、1,2,3的划分步骤较为难懂, 建议画图按照步骤执行一遍
# coding:utf8
def quick_sort(list_temp, start, end):
""" 需排序列表, 开头下标, 尾部下标"""
if start >= end:
# 当只有一个数值进行比较那么头下标和尾下标相同,此时无需比较,跳出递归
return
low = start
high = end
mid = list_temp[start] # 假设第一个值作为中间值
while low < high:
# 尾下标往前移动
while low < high and mid <= list_temp[high]:
high -= 1
list_temp[low] = list_temp[high]
# 头下标往后移动
# 因为希望尽量保证稳定性,如果右边出现与中间值相等的,但依然后出现,这里当做是小于中间值,故需要调到后面
while low < high and list_temp[low] < mid:
low += 1
list_temp[high] = list_temp[low]
list_temp[high] = mid
# 左边
quick_sort(list_temp, start, high-1)
# 右边
quick_sort(list_temp, high+1, end)
if __name__ == '__main__':
# 调用
l = [3, 0, 1, 8, 7, 2, 5, 4, 9, 6]
quick_sort(l, 0, len(l)-1)
print(l)
最优时间复杂度:O(nlogn) 最坏时间复杂度:O(n2) 不稳定
6、归并排序
释义:
1、将序列不断的一分为二直到只有一个元素(一个元素时肯定是个有序的序列,因为只有自己);
2、再将拆分的序列拿两个进行比较大小合并,得到一个新的有序序列;
3、再将这个有序序列拿到和下一个序列合并;
4、.......以此类推,直到将所有拆分的元素合并完
# coding:utf8
def merge_sort(li):
"""将序列对半拆分"""
if len(li) == 1:
# 跳出递归,当长度为1是,即只有一个元素,直接返回自己
return li
mid = len(li) // 2
left_li = li[:mid]
right_li = li[mid:]
# 递归调用,继续分割左边
new_l_list = merge_sort(left_li)
# 递归调用,继续分割右边
new_r_list = merge_sort(right_li)
# 将拆分的合并成新的有序列表
new_sort_nums = merge(new_l_list, new_r_list)
# 将新序列返回
return new_sort_nums
def merge(left_li, right_li):
"""将两个有序的序列合并成新的有序序列,并将这个新的有序序列返回"""
result = [] # 新的序列
l_index = 0 # 左边序列下标
r_index = 0 # 右边序列下标
while l_index < len(left_li) and r_index < len(right_li):
if left_li[l_index] <= right_li[r_index]:
result.append(left_li[l_index])
l_index += 1
else:
result.append(right_li[r_index])
r_index += 1
# 跳出循环说明至少是其中的一个序列比较完了,将未比较完的直接加入到新序列中(以为两个序列分别是有序的)
result += left_li[l_index:]
result += right_li[r_index:]
return result
if __name__ == '__main__':
# 调用
l = [3, 0, 1, 8, 7, 2, 5, 4, 9, 6]
print(merge_sort(l))
思路运行大体步骤:
原序列:
[3, 0, 1, 8, 7, 2, 5, 4, 9, 6]代码先左后右:
左边: 右边:
[3, 0, 1, 8, 7] [2, 5, 4, 9, 6]
[3, 0] [1, 8, 7] [2, 5] [4, 9, 6]
[3] [0] [1] [8, 7] [2] [5] [4] [9, 6]
[8] [7] [9] [6]
[0, 3] [2, 5]
[7, 8] [6, 9]
[1, 7, 8] [4, 6, 9]
[0, 1, 3, 7, 8] [2, 4, 5, 6, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
最坏时间复杂度:O(nlogn) 最优时间复杂度:O(nlogn) 稳定
哎唷卧槽,终于看完了!!!这可能是小伙伴们的心声,不过我也想说终于整完了。。。
目前在学习cpython,所以就贴了Python版本,希望大Python能带我飞啊~~~~~~
欢迎一起分享和交流python---->q群:556993881