四种常见排序(冒泡、选择、插入、快速排序)--- Python版

news2024/11/28 12:54:44

经典排序算法总结与实现

经典排序算法在面试中占有很大的比重,也是基础,为了未雨绸缪,这次收集整理并用Python实现了八大经典排序算法,包括冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序以及基数排序。希望能帮助到有需要的同学。之所以用 Python 实现,主要是因为它更接近伪代码,能用更少的代码实现算法,更利于理解。

本篇博客所有排序实现均默认从小到大

一、冒泡排序BubbleSort

介绍:
冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。

步骤:

  1. 比较相邻的元素,如果第一个比第二个大,就交换他们两个;
  2. 对第0个到第n-1个数据做同样的工作。这时,最大的数就“浮”到了数组最后的位置上;
  3. 针对所有的元素重复以上的步骤,除了最后一个;
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较;

Python源代码(错误版本):

def bubble_sort(arry):
    n = len(arry)                   #获得数组的长度
    for i in range(n):
        for j in range(i+1, n):
            if  arry[i] > arry[j] :       #如果前者比后者大
                arry[i],arry[j] = arry[j],arry[i]      #则交换两者
    return arry

注:上述代码是没有问题的,但是实现却不是冒泡排序,而是选择排序(原理见选择排序),注意冒泡排序的本质是“相邻元素”的顺序交换,而非每次完成一个最小数字的选定。

Python源代码(正确版本):

def bubble_sort(arry):
    n = len(arry)                   #获得数组的长度
    for i in range(n):
        for j in range(1, n-i):    # 每轮找到最大数值 或者用 for j in range(i+1, n)
            if  arry[j-1] > arry[j] :       #如果前者比后者大
                arry[j-1],arry[j] = arry[j], arry[j-1]      #则交换两者
    return arry

不过针对上述代码还有两种优化方案。

优化1:
某一趟遍历如果没有数据交换,则说明已经排好序了,因此不用再进行迭代了。用一个标记记录这个状态即可。

Python源代码:

def bubble_sort2(ary):
	n = len(ary)
	for i in range(n):
		flag = True    # 标记
		for j in range(1, n - i):
			if ary[j] < ary[j-1]:
				ary[j], ary[j-1] = ary[j-1], ary[j]
				flag = False
		# 某一趟遍历如果没有数据交换,则说明已经排好序了,因此不用再进行迭代了
		if flag:    
			break
	return ary

优化2:
记录某次遍历时最后发生数据交换的位置,这个位置之后的数据显然已经有序,不用再排序了。因此通过记录最后发生数据交换的位置就可以确定下次循环的范围了。

def bubble_sort3(ary):
	n = len(ary)
	k = n    #k为循环的范围,初始值n
	for i in range(n):
		flag = True
		for j in range(1, k):    #只遍历到最后交换的位置即可
			if ary[j-1] > ary[j]:
				ary[j-1], ary[j] = ary[j], ary[j-1]
				k = j     #记录最后交换的位置
				flag = False
		if flag:
			break
	return ary

注:上面for j in range(1,k),这句很有意思,虽然后面有if ary[j-1] > ary[j]则k = j,但是这个k不会直接就变动,不然试想,当j=1,0与1位置坐了交换之后,k=j=1,j这一步循环直接就挂掉了,事实上,k的改变是在下一轮i坐了改变之后才会真正起作用,所以j可以记录最后交换位置。

二、选择排序SelectionSort

介绍:
选择排序是另一个很容易理解和实现的简单排序算法。学习它之前首先要知道它的两个很鲜明的特点。

  1. 运行时间和输入无关
    为了找出最小的元素而扫描一遍数组并不能为下一遍扫描提供任何实质性帮助的信息。因此使用这种排序的我们会惊讶的发现,一个已经有序的数组或者数组内元素全部相等的数组和一个元素随机排列的数组所用的排序时间竟然一样长!而其他算法会更善于利用输入的初始状态,选择排序则不然。
  2. 数据移动是最少的
    选择排序的交换次数和数组大小关系是线性关系,选择排序无疑是最简单直观的排序。看下面的原理时可以很容易明白这一点。

步骤:

  1. 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置;
  2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾;
  3. 以此类推,直到所有元素均排序完毕。

源代码:(python实现)

def select_sort(ary):
    n = len(ary)
    for i in range(0,n):
        min = i                             #最小元素下标标记
        for j in range(i+1,n):
            if ary[j] < ary[min] :
                min = j                     #找到最小值的下标
        ary[min],ary[i] = ary[i],ary[min]   #交换两者
    return ary

三、插入排序 InsertionSort

介绍:
插入排序的工作原理是,对于每个未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序;
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  3. 如果被扫描的元素(已排序)大于新元素,将该元素后移一位;
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  5. 将新元素插入到该位置后;
  6. 重复步骤2~5

排序演示
请添加图片描述

源代码:(python实现)

def insert_sort(ary):
	count = len(ary)
	for i in range(1, count):
		key = i - 1
		mark = ary[i]    # 注: 必须将ary[i]赋值为mark,不能直接用ary[i]
		while key >= 0 and ary[key] > mark:
			ary[key+1] = ary[key]
			key -= 1
		ary[key+1] = mark
	return ary

四、快速排序 QuickSort

介绍:
快速排序通常明显比同为Ο(n log n)的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。可见掌握快排的重要性。

步骤:

  1. 从数列中挑出一个元素作为基准数;
  2. 分区过程,将比基准数大的放到右边,小于或等于它的数都放到左边;
  3. 再对左右区间递归执行第二步,直至各区间只有一个数。

虽然快速排序称为分治法,但分治法这三个字显然无法很好的概括快速排序的全部步骤。因此我的对快速排序作了进一步的说明:挖坑填数+分治法:

先来看实例吧,定义下面再给出(最好能用自己的话来总结定义,这样对实现代码会有帮助)。

以一个数组作为示例,取区间第一个数为基准数。

0123456789
7265788604283734885

初始时,i = 0; j = 9; X = a[i] = 72

由于已经将a[0]中的数保存到X中,可以理解成在数组a[0]上挖了个坑,可以将其它数据填充到这来。

从j开始向前找一个比X小或等于X的数。当j=8,符合条件,将a[8]挖出再填到上一个坑a[0]中。a[0]=a[8]; i++; 这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。这次从i开始向后找一个大于X的数,当i=3,符合条件,将a[3]挖出再填到上一个坑中a[8]=a[3]; j–;

数组变为:

0123456789
4865788604283738885

i = 3; j = 7; X=72

再重复上面的步骤,先从后向前找,再从前向后找。

从j开始向前找,当j=5,符合条件,将a[5]挖出填到上一个坑中,a[3] = a[5]; i++;

从i开始向后找,当i=5时,由于i==j退出。

此时,i = j = 5,而a[5]刚好又是上次挖的坑,因此将X填入a[5]。

数组变为:

0123456789
4865742607283738885

可以看出a[5]前面的数字都小于它,a[5]后面的数字都大于它。因此再对a[0…4]和a[6…9]这二个子区间重复上述步骤就可以了。

对挖坑填数进行总结:

  1. i =L; j = R; 将基准数挖出形成第一个坑a[i];
  2. j–由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中;
  3. i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中;
  4. 再重复执行2,3二步,直到i==j,将基准数填入a[i]中。

照着这个总结很容易实现挖坑填数的代码.

排序演示
请添加图片描述

源代码:(python实现)

def quick_sort(ary):
    return qsort(ary, 0, len(ary) - 1)


def qsort(ary, start, end):
    if start < end:
        left = start
        right = end
        key = ary[start]
    else:
        return ary
    while left < right:
        while left < right and ary[right] >= key:
            right -= 1
        if left < right:  # 说明打破while循环的原因是ary[right] <= key
            ary[left] = ary[right]
            left += 1
        while left < right and ary[left] < key:
            left += 1
        if left < right:  # 说明打破while循环的原因是ary[left] >= key
            ary[right] = ary[left]
            right -= 1
    ary[left] = key  # 此时,left=right,用key来填坑

    qsort(ary, start, left - 1)
    qsort(ary, left + 1, end)
    return ary

另外一种实现方法
先从待排序的数组中找出一个数作为基准数(取第一个数即可),然后将原来的数组划分成两部分:小于基准数的左子数组和大于等于基准数的右子数组。然后对这两个子数组再递归重复上述过程,直到两个子数组的所有数都分别有序。最后返回“左子数组” + “基准数” + “右子数组”,即是最终排序好的数组。

源代码:(python实现)
实现快排

def quicksort(nums):
    if len(nums) <= 1:
        return nums

    # 左子数组
    less = []
    # 右子数组
    greater = []
    # 基准数
    base = nums.pop()

    # 对原数组进行划分
    for x in nums:
        if x < base:
            less.append(x)
        else:
            greater.append(x)

    # 递归调用
    return quicksort(less) + [base] + quicksort(greater)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/91799.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python实现批量采集美女视*频 <无水印>

前言 大家早好、午好、晚好吖 ❤ ~ 我给大家准备了一些资料&#xff0c;包括: 2022最新Python视频教程、Python电子书10个G &#xff08;涵盖基础、爬虫、数据分析、web开发、机器学习、人工智能、面试题&#xff09;、Python学习路线图等等 直接在文末名片自取即可&#x…

机器学习还能预测心血管疾病?没错,我用 Python 写出来了

全球每年约有1700万人死于心血管疾病&#xff0c;当中主要表现为心肌梗死和心力衰竭。当心脏不能泵出足够的血液来满足人体的需要时&#xff0c;就会发生心力衰竭&#xff0c;通常由糖尿病、高血压或其他心脏疾病引起。 在检测心血管疾病的早期症状时&#xff0c;机器学习就能…

nodejs+vue企业固定资产管理系统-vscode

目 录 摘 要 I 目 录 III 第一章 概述 1.1研究背景 1.2 开发意义 1.3 研究现状 1.4 研究内容 1.5 论文结构 第二章 开发技术介绍 2.5 B/S架构 3.1 可行性分析 3.1.1技术可行性 3.1.2操作可行性 3.1.3 经济可行性 3.1.4 运行可行性 3.2性能需求分析 3.4功能分析 第四章 系统设计…

轻量级的架构决策记录机制

作者&#xff1a;倪新明 ADR是一种性价比非常高的架构决策文档化实践&#xff0c;团队引入和实践成本很低&#xff0c;却能为团队带来极大收益&#xff01; 1 团队研发面临的问题 不论是在传统的IT行业&#xff0c;还是互联网行业&#xff0c;研发团队在架构决策层面或多或少…

在Arduino IDE上开发ESP32(离线安装SDK)

用过Arduino的朋友都知道&#xff0c;Arduino的整个生态强大得让你不能不服。大家所贡献出来的各种库让基于Arduino的开发虽然还没有变得无所不能&#xff0c;但也算是相当得心应手了。你所能想到的功能大体都能在网上找到对应的库和文章。可能是因为这个原因吧&#xff0c;所以…

Redis整理-未完成

目录 1. Redis安装 1.1 单机 1.2 主从 1.3 哨兵 1.4 集群 1.4.1 方式一 redis-cli --cluster命令 1.4.2 方式二 cluster meet/addslots/replicate 2. Redis配置 2.1 基本参数配置 2.2 持久化配置 2.3 内存策略设置 2.4 主从配置 2.5 哨兵配置 2.6 集群配置 2.6.…

吃透这份 “ 自动化测试 ” 核心技术栈,月薪30K还不是随便叫

为了帮助大家快速回顾学习自动化测试中的知识点&#xff0c;分享一下这些年来&#xff0c;我对于技术一些归纳和总结&#xff0c;和自己对作为一名 高级测试工程师需要掌握那些技能的笔记分享&#xff0c;希望能帮助到有心在技术这条道路上一路走到黑的朋友&#xff01; 一、L…

[附源码]Python计算机毕业设计SSM基于JAVA快递配送平台(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

语音怎么转换成文字?这几个实用方法分享给你

当我们在听一些流行的英文歌曲时&#xff0c;发现它没有附带翻译的时候&#xff0c;是不是常常听不懂歌曲的意思内容呢&#xff1f;面对这种情况应该怎么办呢&#xff1f;其实也不难&#xff0c;我们只需要利用软件来将歌曲转换成文字的格式就可以了&#xff0c;那你们知道如何…

分布式系统(交互、协作)

文章目录进程组织进程交互传染病协议反熵&#xff08;Anti-Entropy&#xff09;闲聊&#xff08;Gossiping&#xff09;P2P 路由Circular routingPastry应用层多播ESMScribe中间件通信协议RPCMOM进程协作有序组播基本组播FIFO 组播全排序组播定序者分布式协商因果序组播分布式互…

基于SSM框架的酒店管理系统

基于SSM框架的酒店管理系统开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 看每个等级模块&#xff1a;客白模块&#xff0c;屋工模垫&#xff0c;反怠管理员模垫 客户可…

如何实现采购管理流程的优化?

采购管理流程优化指的是一种整体方法&#xff0c;而不是个人主义的方法。它指的是利用人员、流程和技术来实现最佳价值创造的过程。采购优化的方法可以是&#xff1a;最初的范围界定&#xff0c;数据收集和分析&#xff0c;改进和实施以及跟进和监控。 理解采购管理流程优化 …

oracle学习篇(二)

oracle学习篇(二) 1添加约束 1.1 添加主键约束 1.1.1 语法 alter table 表名 add constraint 约束名 约束关键字 key(添加约束的字段);1.1.2 示例代码 alter table infos add constraint pk_stuid primary key(stuid);1.2 添加检查约束 1.2.1 语法 alter table 表名 ad…

[附源码]Node.js计算机毕业设计高校学生心理健康信息咨询系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

numpy.pad()函数详解

目录 函数定义&#xff1a; 示例讲解&#xff1a; 示例1.1 constant&#xff1a; 示例1.2 maximum 示例1.3 constant: 示例2.1 constant&#xff1a; 示例2.2 constant&#xff1a; 函数定义&#xff1a; numpy.pad()函数用于对Numpy数组进行填充。有时需要对Numpy数组进…

Docker 项目快速部署Flask项目

前言 打造 flask gunicron nginx Mysql 环境 nginx Mysql 使用docker 快速部署 使用 supervisor 对 gunicron 做监控 环境&#xff1a;centos7 &#xff0c;python3.7 flask 篇 flask 项目就不多赘述了。这里贴一下项目的目录&#xff0c;便于解释下面的命令参数。 运行…

​Word怎么转换成PDF格式?这三种方法教你如何转换

怎么把Word文档转换成PDF文件格式呢&#xff1f;相信小伙伴们在办公过程中会习惯使用Word文档来编辑文件&#xff0c;编辑好后如果需要发送文件的话会将文档转换成PDF格式来发送&#xff0c;原因就是PDF格式独有的兼容性和稳定性能够让我们的文件格式不会错乱&#xff0c;这也是…

深入理解Maven的全部配置

深入理解Maven的全部配置1. Introduction1.1 Big Data -- Postgres2. Install2.1 Maven Install2.2 Config Setting.xml2.3 Local Package Install Maven3. Project4.AwakeningMaven Document: https://maven.apache.org/. Maven Download: https://maven.apache.org/download.…

前端富文本设置的表格样式无法展示解决方案

当我们在富文本编辑器里编辑好文本后&#xff0c;发布一看&#xff0c;为什么编辑器预览的内容和实际保存后展示的内容不一致呢。这是因为&#xff0c;大部分编辑器本身会自带一些样式属性&#xff0c;而当获取富文本内容的时候往往是不带这些样式属性的&#xff0c;所以才导致…

【Java_GUI编程】--基本操作你要知道

文章目录一、组件和容器1、JFrame2、面板JPanel3、布局管理器流式布局&#xff08;从左到右&#xff09;东南西北中网格布局4、事件监听输入框事件监听键盘监听5、JDialog弹窗6、Icon、ImageIcon标签IconImageIcon7、按钮单选按钮复选按钮8、列表下拉框列表框9、文本框密码框文…