一、冒泡排序

原理:

  1. 比较相邻的元素。如果第一个比第二个大就交换他们两个
  2. 每一对相邻元素做同样的工作,直到结尾最后一对
  3. 每个元素都重复以上步骤,除了最后一个

第一步:

将乱序中的最大值找出,逐一移到序列最后的位置

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]

二、选择排序

思路:

  1. 首先在序列中找到最大(小)元素,存放到序列的最后
  2. 在从剩余的序列元素中继续找最大(小)的元素,放到序列中上一个最大值的前一个位置
  3. 重复第二步,直到所有元素排序完毕

第一步:

将乱序中的元素两两比较,找出最大值,然后直接将最大值放置到序列最后的位置(将最大值直接和最后一个元素交换位置)

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

五、快速排序

思路:

  1. 将列表中第一个元素设定为基准数字,赋值给mid变量,然后将整个列表中比基准小的数值放在基准的左侧,比基准大的数字放在基准右侧,然后将基准数字左右两侧的序列在根据此方法进行排放
  2. 定义两个指针,low 指向最左侧,high 指向最右侧
  3. 然后对最右侧指针进行向左移动,移动法则是,如果指针指向的数值比基准小,则将指针指向的数字移动到基准数字原始位置,否则继续移动指针。
  4. 如果最右侧指针指向的数值移动到基准位置时,开始移动最左侧指针,将其向右移动,如果该指针指向的数值大于基准侧将该数值移动到最右侧指针指向的位置,然后停止移动。
  5. 如果左右侧指针重复则,将基准放入左右指针重复的位置,则基准左侧为比其小的数值,右侧为比其大的数值

第一步:

核心操作,将基数 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实现常用五种排序算法的更多相关文章

  1. C#常用8种排序算法实现以及原理简介

    public static class SortExtention { #region 冒泡排序 /* * 已知一组无序数据a[1].a[2].--a[n],需将其按升序排列.首先比较a[1]与a[2 ...

  2. python:实现几种排序算法

    冒泡排序 比较相邻两个字符,如果左边大于右边,则交换位置,遍历一遍字符后,则最大的肯定在最右边:继续循环处理剩下的字符(最右边的不用再比较了,已经最大了) 代码实现: def BubbleSort(s ...

  3. 几种排序算法的学习,利用Python和C实现

    之前学过的都忘了,也没好好做过总结,现在总结一下. 时间复杂度和空间复杂度的概念: 1.空间复杂度:是程序运行所以需要的额外消耗存储空间,一般的递归算法就要有o(n)的空间复杂度了,简单说就是递归集算 ...

  4. java算法03 - 常用的8种排序算法

    Java常用的八种排序算法: 插入排序 - 直接插入排序 每次将待排序的记录按照关键字的大小,插入到前面已经排好序的记录的适当位置.直到全部记录插入完成. 代码实现 /** * 直接插入排序 O(n^ ...

  5. 学习Java绝对要懂的,Java编程中最常用的几种排序算法!

    今天给大家分享一下Java中几种常见的排序算法的Java代码 推荐一下我的Java学习羊君前616,中959,最后444.把数字串联起来!     ,群里有免费的学习视频和项目给大家练手.大神有空时也 ...

  6. 常用七种排序的python实现

    1 算法复杂度 算法复杂度分为时间复杂度和空间复杂度.其中, 时间复杂度是指执行算法所需要的计算工作量:而空间复杂度是指执行这个算法所需要的内存空间. 算法的复杂性体现在运行该算法时的计算机所需资源的 ...

  7. Java 的八种排序算法

    Java 的八种排序算法 这个世界,需要遗忘的太多. 背景:工作三年,算法一问三不知. 一.八种排序算法 直接插入排序.希尔排序.简单选择排序.堆排序.冒泡排序.快速排序.归并排序和基数排序. 二.算 ...

  8. 用 C 语言描述几种排序算法

    排序算法是最基本且重要的一类算法,本文基于 VS2017,使用 C 语言来实现一些基本的排序算法. 一.选择排序 选择排序,先找到数组中最小的元素,然后将这个元素与数组的第一个元素位置互换(如果第一个 ...

  9. Python实现十大经典排序算法(史上最简单)。

    十大排序算法(Python实现)一. 算法介绍及相关概念解读 算法分类十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn), ...

随机推荐

  1. 『心善渊』Selenium3.0基础 — 12、Selenium操作鼠标和键盘事件

    目录 (一)对鼠标的操作 1.鼠标事件介绍 2.ActionChains 类鼠标操作的常用方法 3.perform()方法 4.鼠标事件操作步骤 5.示例 (1)右键单击.左键双击 (2)鼠标拖拽动作 ...

  2. 重新整理 .net core 实践篇————网关中的身份签名认证[三十七]

    前言 简单整理一下网关中的jwt,jwt用于授权认证的,其实关于认证授权这块https://www.cnblogs.com/aoximin/p/12268520.html 这个链接的时候就已经写了,当 ...

  3. AcWing 920. 最优乘车

    H城是一个旅游胜地,每年都有成千上万的人前来观光. 为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴士线路. 每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站, ...

  4. RabbitMQ重试机制

    消费端在处理消息过程中可能会报错,此时该如何重新处理消息呢?解决方案有以下两种. 在redis或者数据库中记录重试次数,达到最大重试次数以后消息进入死信队列或者其他队列,再单独针对这些消息进行处理: ...

  5. linux命令-------find命令之exec

    p.p1 { margin: 0; font: 18px "Hannotate SC"; color: rgba(4, 51, 255, 1); -webkit-text-stro ...

  6. 《Linux基础知识及命令》系列分享专栏

    <Linux基础知识及命令>系列分享专栏 本专题详细为大家讲解了Linux入门基础知识,思路清晰,简单易懂.本专题非常适合刚刚学习Linux的小白来学习,通过学习该专题会让你由入门达到中级 ...

  7. 淘宝的sign参数js逆向

    前言:现在网站都有很强的反爬机制,都是非常常见的是用js前端加密参数,所以不得不去分析和逆向js混淆后的代码 一. 打开天猫或淘宝,shift+ctrl+F12全局搜索sign参数. 这里发现很多地方 ...

  8. 全彩LED灯

    1.全彩 LED 灯,实质上是一种把红.绿.蓝单色发光体集成到小面积区域中的 LED 灯,控制时对这三种颜色的灯管输出不同的光照强度,即可混合得到不同的颜色,其混色原理与光的三原色混合原理一致.例如, ...

  9. Python单元测试框架unittest之单用例管理(二)

    概述 利用python进行测试时,测试用例的加载方式有2种: 一种是通过unittest.main()来启动所需测试的测试模块,上篇文章就是使用的这种方式: 一种是添加到testsuite集合中再加载 ...

  10. Chirp Z-Transform

    Chirp Z-Transform 其实不是什么特别难的东西. 用于解决等比数列/类等比数列多点求值. \(b_i=\sum_{j=0}^{n}a_jc^{ij}\) 注意到 \(ij=\binom{ ...