python实现常用五种排序算法
一、冒泡排序
原理:
- 比较相邻的元素。如果第一个比第二个大就交换他们两个
- 每一对相邻元素做同样的工作,直到结尾最后一对
- 每个元素都重复以上步骤,除了最后一个

第一步:
将乱序中的最大值找出,逐一移到序列最后的位置
alist = [3, 5, 9, 2, 1, 7, 8, 6, 4]
def bubble_sort(alist):
# 找最大值的方式是通过对列表中的元素进行两两比较,值大的元素逐步向后移动
# 序列中有n个元素,两两比较的话,需要比较n-1次
for i in range(len(alist) - 1): # 循环n-1次,控制两两比较的次数
if alist[i] > alist[i + 1]:
# 如果前面的元素大于后面的元素,交换两个元素的位置,否则不做任何操作
alist[i], alist[i + 1] = alist[i + 1], alist[i]
return alist
print(bubble_sort(alist))
# 输出:最大值已经移动到最右边了
[3, 5, 2, 1, 6, 7, 8, 4, 9]
当上述代码已经可以将序列中的最大值放置到合适的位置,然后我们就可以将上述操作继续作用到 n-1 和元素对应的新序列,则就可以将 n-1 个元素对应的最大值放置到了 n-1 和元素的最后位置。
结论:发现如果将上述的操作逐步的作用 n-1 此就可以将整个序列变成有序的。
第二步:
将第一步的操作继续作用 n-1 次
alist = [3, 5, 9, 2, 1, 7, 8, 6, 4]
def bubble_sort(alist):
for j in range(len(alist)-1): # 外层循环次数递增,内层循环次数递减
for i in range(len(alist) - 1-j): # 循环次数需要递减-j,控制两两比较的次数
if alist[i] > alist[i + 1]:
# 如果前面的元素大于后面的元素,交换两个元素的位置,否则不做任何操作
alist[i], alist[i + 1] = alist[i + 1], alist[i]
return alist
print(bubble_sort(alist))
# 输出
[1, 2, 3, 4, 5, 6, 7, 8, 9]
二、选择排序
思路:
- 首先在序列中找到最大(小)元素,存放到序列的最后
- 在从剩余的序列元素中继续找最大(小)的元素,放到序列中上一个最大值的前一个位置
- 重复第二步,直到所有元素排序完毕
第一步:
将乱序中的元素两两比较,找出最大值,然后直接将最大值放置到序列最后的位置(将最大值直接和最后一个元素交换位置)
def select_sort(alist):
max_index = 0 # 最大值元素的下标,一开始假设下标为0的元素为最大值
for i in range(len(alist) - 1): # 循环控制两两比较的次数
# 如果在比较的过程中发现,下标为max_index不是最大值,那么就改变max_index
if alist[max_index] < alist[i + 1]:
max_index = i + 1
# 循环结束后max_index就一定是最大值的下标,并且把该数和最后一个值做交换
alist[len(alist) - 1], alist[max_index] = alist[max_index], alist[len(alist) - 1]
return alist
alist = [3, 5, 9, 2, 1, 7, 8, 6, 4]
print(select_sort(alist))
# 输出
[3, 5, 4, 2, 1, 7, 8, 6, 9]
第二步:
将第一步继续作用 n-1 次
def select_sort(alist):
for j in range(len(alist) - 1):# 外层循环递增n-1次
max_index = 0 # 最大值元素的下标,一开始假设下标为0的元素为最大值
for i in range(len(alist) - 1 - j): # 内层循环递减,循环控制两两比较的次数
# 如果在比较的过程中发现,下标为max_index不是最大值,那么就改变max_index
if alist[max_index] < alist[i + 1]:
max_index = i + 1
# 循环结束后max_index就一定是最大值的下标,并且把该数和最后一个值做交换
alist[len(alist) - 1 - j], alist[max_index] = alist[max_index], alist[len(alist) - 1 - j]
return alist
alist = [3, 5, 9, 2, 1, 7, 8, 6, 4]
print(select_sort(alist))
三、插入排序
思路:
- 需要将原始序列分为两个部分:有序部分、无序部分。
- 将无序部分中的元素逐一插入到有序部分中
注意:初始情况下,有序部分为乱序序列中的第一个元素,无序部分为乱序序列的 n-1 个元素
例如:
# 乱序序列:[8,3,5,7,6]
[8, 3,5,7,6] # 8就是初始的有序部分,3、5、7、6就是初始的无序部分
[3,8, 5,7,6]
[3,5,8, 7,6]
[3,5,7,8, 6]
[3,5,7,6,8, ]
第一步:
定义一个变量 i ,i 表示的是有序部分元素的个数和无序部分第一个元素小标
alist = [8, 3, 1, 6, 7]
i = 1 # i 就是有序部分元素的个数和无序部分第一个元素下标
# alist[i-1]:有序部分最后一个元素下标
# alist[i]:无序部分第一个元素下标
if alist[i - 1] > alist[i]:
alist[i], alist[i - 1] = alist[i - 1], alist[i]
# [3, 8, 1, 6, 7]
第二步:循环作用到每个元素中
alist = [8, 3, 1, 6, 7]
i = 2
# alist[i-1]:有序部分最后一个元素下标
# alist[i]:无序部分第一个元素下标
while i > 0:
if alist[i - 1] > alist[i]:
# 循环第一次时[3,1,8, 6,7]
alist[i], alist[i - 1] = alist[i - 1], alist[i]
i -= 1
# 循环继续
# [1,3,8, 6,7]
else:
break
第三步:
处理变量 i,需要让 i 进行自己递增
for i in range(1, len(alist)): # i = [1,2,3,4]
# alist[i-1]:有序部分最后一个元素下标
# alist[i]:无序部分第一个元素下标
while i > 0:
if alist[i - 1] > alist[i]:
alist[i], alist[i - 1] = alist[i - 1], alist[i]
i -= 1
else:
break
完整代码:
def insert_sort(alist):
for i in range(1, len(alist)):
while i > 0:
if alist[i - 1] > alist[i]:
alist[i - 1], alist[i] = alist[i], alist[i - 1]
i -= 1
else:
break
return alist
四、希尔排序
关键变量:增量gap
gap:初始值为 len(alist) // 2
- 表示分组的组数
- 每一组数据之间的间隔
插入排序就是增量为 1 的希尔排序

第一步:
将插入排序代码写出
def hill_sort(alist):
for i in range(1, len(alist)):
while i > 0:
if alist[i - 1] > alist[i]:
alist[i - 1], alist[i] = alist[i], alist[i - 1]
i -= 1
else:
break
return alist
第二步:
在插入排序代码中加入增量的概念
def hill_sort(alist):
gap = len(alist) // 2 # 初识增量
# 将插入排序中的增量1替换成gap
# 由增量1变成了增量为gap了
for i in range(gap, len(alist)):
while i > 0:
if alist[i - gap] > alist[i]:
alist[i - gap], alist[i] = alist[i], alist[i - gap]
i -= gap
else:
break
return alist
第三步:
在第二步中进行增量的缩减(增量缩减到1结束)完整代码
def hill_sort(alist):
gap = len(alist) // 2 # 初识增量
while gap >= 1:
for i in range(gap, len(alist)):
while i > 0:
if alist[i - gap] > alist[i]:
alist[i - gap], alist[i] = alist[i], alist[i - gap]
i -= gap
else:
break
gap //= 2 # 缩减增量
return alist
五、快速排序
思路:
- 将列表中第一个元素设定为基准数字,赋值给mid变量,然后将整个列表中比基准小的数值放在基准的左侧,比基准大的数字放在基准右侧,然后将基准数字左右两侧的序列在根据此方法进行排放
- 定义两个指针,low 指向最左侧,high 指向最右侧
- 然后对最右侧指针进行向左移动,移动法则是,如果指针指向的数值比基准小,则将指针指向的数字移动到基准数字原始位置,否则继续移动指针。
- 如果最右侧指针指向的数值移动到基准位置时,开始移动最左侧指针,将其向右移动,如果该指针指向的数值大于基准侧将该数值移动到最右侧指针指向的位置,然后停止移动。
- 如果左右侧指针重复则,将基准放入左右指针重复的位置,则基准左侧为比其小的数值,右侧为比其大的数值
第一步:
核心操作,将基数 mid 放置到序列中间,使得基数左侧都是比它小的,右侧是比它大的
def quick_sort(alist):
low = 0 # 第一个元素下标
high = len(alist) - 1 # 最后一个元素下标
mid = alist[low] # 基数:初始值为序列中的第一个数值
while low != high:
# 先移动high
while low < high:
if mid < alist[high]: # 下标high对应的值大于mid,high就向右偏移1
high = high - 1
else:
# 否则,就把将high指向的数值放置到左侧下标为low对应的空位
alist[low] = alist[high]
break # 传递后high下标偏移结束
# 开始移动low
while low < high:
if mid > alist[low]: # 下标low对应的值小于mid,low就向左偏移1
low = low + 1
else:
# 否则,就把将low指向的数值放置到左侧下标为high对应的空位
alist[high] = alist[low]
break # 并结束
# 最后当low和high相等的时候,那么就把mid传给下标为low或high的位置
alist[low] = mid
return alist
alist = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8]
print(quick_sort(alist))
# 输出——>6左边都是比6小的,右边都是比6大的
[5, 1, 2, 4, 3, 6, 9, 7, 10, 8]
第二步:
将第一步的核心操作递归作用到基数的左右两侧的子序列中
# 那么如何区分根据基数拆分出的左右子序列呢?可以通过传入指定的left和right来指定不同的子序列
def quick_sort(alist, left, right):
low = left # 第一个元素下标
high = right # 最后一个元素下标
if low > high: # 递归结束条件,low是不能大于high的
return
mid = alist[low] # 基数:初始值为序列中的第一个数值
while low != high:
# 先移动high
while low < high:
if mid < alist[high]: # 下标high对应的值大于mid,high就向右偏移1
high -= 1
else:
# 否则,就把将high指向的数值放置到左侧下标为low对应的空位
alist[low] = alist[high]
break # 传递后high下标偏移结束
# 开始移动low
while low < high:
if mid >= alist[low]: # 下标low对应的值小于mid,low就向左偏移1
low += 1
else:
# 否则,就把将low指向的数值放置到左侧下标为high对应的空位
alist[high] = alist[low]
break # 并结束
# 最后当low和high相等的时候,那么就把mid传给下标为low或high的位置
if low == high:
alist[low] = mid
# 上述为核心操作,需要将核心操作递归作用到左右子序列中
quick_sort(alist, left, low - 1) # 递归到左侧序列中
quick_sort(alist, high + 1, right) # 递归到右侧序列中
return alist
alist = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8]
print(quick_sort(alist, 0, len(alist) - 1))
# 输出
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
python实现常用五种排序算法的更多相关文章
- C#常用8种排序算法实现以及原理简介
public static class SortExtention { #region 冒泡排序 /* * 已知一组无序数据a[1].a[2].--a[n],需将其按升序排列.首先比较a[1]与a[2 ...
- python:实现几种排序算法
冒泡排序 比较相邻两个字符,如果左边大于右边,则交换位置,遍历一遍字符后,则最大的肯定在最右边:继续循环处理剩下的字符(最右边的不用再比较了,已经最大了) 代码实现: def BubbleSort(s ...
- 几种排序算法的学习,利用Python和C实现
之前学过的都忘了,也没好好做过总结,现在总结一下. 时间复杂度和空间复杂度的概念: 1.空间复杂度:是程序运行所以需要的额外消耗存储空间,一般的递归算法就要有o(n)的空间复杂度了,简单说就是递归集算 ...
- java算法03 - 常用的8种排序算法
Java常用的八种排序算法: 插入排序 - 直接插入排序 每次将待排序的记录按照关键字的大小,插入到前面已经排好序的记录的适当位置.直到全部记录插入完成. 代码实现 /** * 直接插入排序 O(n^ ...
- 学习Java绝对要懂的,Java编程中最常用的几种排序算法!
今天给大家分享一下Java中几种常见的排序算法的Java代码 推荐一下我的Java学习羊君前616,中959,最后444.把数字串联起来! ,群里有免费的学习视频和项目给大家练手.大神有空时也 ...
- 常用七种排序的python实现
1 算法复杂度 算法复杂度分为时间复杂度和空间复杂度.其中, 时间复杂度是指执行算法所需要的计算工作量:而空间复杂度是指执行这个算法所需要的内存空间. 算法的复杂性体现在运行该算法时的计算机所需资源的 ...
- Java 的八种排序算法
Java 的八种排序算法 这个世界,需要遗忘的太多. 背景:工作三年,算法一问三不知. 一.八种排序算法 直接插入排序.希尔排序.简单选择排序.堆排序.冒泡排序.快速排序.归并排序和基数排序. 二.算 ...
- 用 C 语言描述几种排序算法
排序算法是最基本且重要的一类算法,本文基于 VS2017,使用 C 语言来实现一些基本的排序算法. 一.选择排序 选择排序,先找到数组中最小的元素,然后将这个元素与数组的第一个元素位置互换(如果第一个 ...
- Python实现十大经典排序算法(史上最简单)。
十大排序算法(Python实现)一. 算法介绍及相关概念解读 算法分类十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn), ...
随机推荐
- Pandas高级教程之:category数据类型
目录 简介 创建category 使用Series创建 使用DF创建 创建控制 转换为原始类型 categories的操作 获取category的属性 重命名categories 使用add_cate ...
- 微信获取信息发生错误(两个access_token的区别),错误代码:40001,说明:invalid credential, access_token is invalid or not latest hints
微信有两个access_token,一个是基础access_token,一个是网页授权access_token. 想要获取不带unionid的用户信息(以下链接)使用基础access_token ht ...
- ubuntu 18.4LTS 安装12.1.6赛门铁克防病毒系统
创建/tools/ 文件夹,并将需要的软件包上传到该目录下 # mkdir -p /tools/ && cd /tools/ # tar -xzvf chang.tar.gz # cd ...
- 07 修改JumpServer网页信息
1.7.修改JumpServer网页信息 注意:在修改相关配置文件之前要先进行备份,防止文件修改错误无法恢复. 1.Luna图标: /opt/luna/static/imgs/logo.png 2.j ...
- 6、负载均衡HAproxy介绍
6.1.常用负载均衡器软件说明: 现在常用的三大开源软件负载均衡器分别是Nginx.HAProxy.LVS. 1.nginx负载均衡的特点: (1)工作在网络的七层之上,可以针对http应用做一些分流 ...
- webpack(4)webpack.config.js配置和package.json配置
前言 上一篇文章我们使用webpack打包成功了,但是每次都要自己手动输入打包的文件地址和打包到哪里去的地址,非常麻烦,所以这里介绍使用配置文件进行打包 webpack.config.js 首先我们创 ...
- docker搭建数据库高可用方案PXC
前言 本方案主要目的是学习, 该方案不太合适于企业项目 是什么? 白话点, 是个提供了必要环境的虚拟机(类似于java的导入部分包一样和c++的头文件差不多), 所以它比普通的VMWare或者Virt ...
- PV操作的概念
PV操作:一种实现进程互斥与同步的有效方法,包含P操作与V操作. P操作:使 S=S-1 ,若 S>=0 ,则该进程继续执行,否则排入等待队列. V操作:使 S=S+1 ,若 S>0 ,唤 ...
- svn创建新分支报错:svn: E155015: Aborting commit: XXX remains in conflict
用diea在对svn创建新分支的时候报错,错误为 svn: E155015: Aborting commit: XXX remains in conflict 百度和查阅资料后得知,此错误为分支被拉取 ...
- 滑动窗口通用解leetcode字符串匹配问题
滑动窗口,这玩意解决一些字符串匹配的题目是真的挺好用的,虽然本质还是双指针. 思路: 1.维护一个窗口,不断的向右边移动 2.满足要求后,移动左边,当不满足时,跳出. 3.重复1,2.得出答案. 下面 ...