排序算法整理(Python实现)
1. 冒泡排序
冒泡排序(Bubble Sort)是稳定排序,其基本思想是:遍历待排序列,依次两两比较,如果顺序错误就交换。如果从头开始遍历,把较大的交换到后面,结果就是越大的数据越往下沉,所以也可以称为“下沉排序”;如果从尾开始向前遍历,把较小的交换到前面,结果就是越小的数据越往上浮,这就是“冒泡排序”名称的由来。冒泡排序比较简单,python实现如下:
def bubble_sort(array):
length = len(array)
for i in range(0, length): # 这轮遍历只是表示整个排序最大需要几轮
j = length - 1 # 这个例子从后开始遍历,演示的是“上浮冒泡排序”
while j >= i: # 每轮遍历只需要剩下的比较未排序的序列,前i个元素已经有序了(也就是说整个序列下标小于i的元素都已经有序)
if array[j] < array[j-1]:
array[j-1], array[j] = array[j], array[j-1]
j -= 1
上面的例子是不管待排序列本身是否有序,全部遍历。而实际上待排序列可能本身就已经有序(或部分有序),这样在遍历并比较的过程中就不会交换数据。也就是说如果在某一轮的遍历过程中没有交换数据,就说明整个序列已经有序了。所以上面的代码还可以略做优化:
def optimized_bubble_sort(array):
length = len(array)
has_switched = True # 是否有数据交换
for i in range(0, length): # 这轮遍历只是表示整个排序最大需要几轮
# 没有数据交换,说明序列有序,退出循环,完成排序
if has_switched is False:
break
has_switched = False # 每轮比较,初始假设没有数据交换
j = length - 1 # 这个例子从后开始遍历,演示的是“上浮冒泡排序”
while j >= i: # 每轮遍历只需要剩下的比较未排序的序列,前i个元素已经有序了(也就是说整个序列下标小于i的元素都已经有序)
if array[j] < array[j-1]:
array[j-1], array[j] = array[j], array[j-1]
has_switched = True # 有数据交换
j -= 1
2. 选择排序
选择排序(Selection Sort)是不稳定排序,它的过程为:从整个序列中找出最小的元素和第一个元素交换,然后再从剩下的序列中找出最小的和第二个元素交换...,共需重复待排序列的长度减一的次数,最终得到一个有序序列。Python实现如下:
def simple_selection_sort(array):
length = len(array) # 获取最后一个元素的下标
# 需要遍历 len(array) - 1 次。因为前面的都排好序后,最后只剩一个元素,
# 而且最后的这个元素是前面比较替换之后确定的一个元素,自然是有序的
for i in range(length-1):
index_min_value = i # index_min_value 为最小元素对应的下标,假设下标为i的元素最小
# 从剩下的元素里面找出最小的
for j in range(i+1, length):
if array[j] < array[index_min_value]:
index_min_value = j
# 如果第i个元素不是最小的,将最小元素与第i个元素交换位置
if index_min_value != i:
array[i], array[index_min_value] = array[index_min_value], array[i]
3. 插入排序
插入排序(Insertion Sort)是稳定排序,它的基本操作是将一条记录插入到已经排好序的有序序列中,从而得到一个新的、记录数增1的有序序列。具体实现为:从待排序列的第二个元素开始,将当前元素抽出来插入到前面的有序序列中。第一步抽出第2个元素(它的前面就只有一个元素,可以看做是只包含一个元素的有序序列),然后将这第2个元素插入到前面的有序序列中,得到一个有两个元素的有序序列。第二步抽出第3个元素,重复第一步的操作。最后就得到一个完整的有序序列。
def insertion_sort(array):
# i 从第2个元素开始
for i in range(1, len(array)):
# 第i个元素之前的序列是有序序列,这里将第i个元素插入到之前的有序序列中
# 插入第i个元素完成后的有序序列长度会多一个,这里先将第i个元素暂存起来,空出位置
temp_value = array[i]
# 第i个位置已经是空位了,从第i-1个元素逆向遍历,将 temp_value 插入到合适的位置
j = i
while j > 0 and array[j-1] > temp_value:
array[j] = array[j-1] # 就是将第j-1个元素后移一个位置
j -= 1
# 最后第j个位置就是 temp_value 需要插入的位置
array[j] = temp_value
4. 归并排序
归并排序(Merge Sort)是稳定排序。归并排序采用D&C(分治,divide and conquer)策略,首先将待排序列分解成有序序列(空序列或只包含一个元素的序列可以看做是有序序列),再讲每个有序序列归并,最终得到一个完整的有序序列。
def merge_sort(array):
if len(array) <= 1: # 基线条件,此时的序列就是有序序列,分解的停止条件
return array
# 分解待排序列
mid = len(array) // 2
left = merge_sort(array[:mid]) # 递归调用自身,直到子序列有序,即达到上面的基线条件
right = merge_sort(array[mid:])
# 合并有序的子序列
return merge(left, right)
def merge(left, right):
"""
合并left、right,left和right均为有序序列
"""
result = [] # 结果集
left_pointer = 0 # 指向left的指针,初始指向left的第一个元素
right_pointer = 0 # 指向right的指针,初始指向right的第一个元素
# 从left的第一个元素和right的第一个元素开始对比,
# 哪边的元素较小则将哪边的元素放入result,并将较小元素的指针往后移一位
while left_pointer < len(left) and right_pointer < len(right):
if left[left_pointer] < right[right_pointer]:
result.append(left[left_pointer])
left_pointer += 1
else:
result.append(right[right_pointer])
right_pointer += 1
if left_pointer == len(left):
# 左边的指针已经指向left的最后一个元素,说明左边的元素已经全部添加到result了,直接把右边剩下的依次追加到result
for i in right[right_pointer:]:
result.append(i)
else:
# 否则就是右边的元素已经全部添加到result了,直接把左边剩下的依次追加到result
for i in left[left_pointer:]:
result.append(i)
return result
5. 快速排序
快速排序(Quick Sort)是不稳定排序。快速排序也采用了D&C策略,首先选取一个基准值,然后通过一次遍历将待排序列分成三部分(这被称为分区,partitioning):所有元素都小于或者等于基准值的一个序列less_array、基准值、所有元素都大于基准值的一个序列grater_array。这个时候对整个序列排序就很容易了:less_array + 基准值 + grater_array,对于less_array和grater_array再分别采用递归的方式进行快速排序,最后得到整个待排序列的一个有序序列。
def quick_sort(array):
if len(array) < 2: # 退出递归的基线条件
return array
pivot = array[0] # 基准值,可随便选取
# 分区
less_array = [i for i in array[1:] if i <= pivot]
grater_array = [j for j in array[1:] if j > pivot]
# 采用一次遍历分区的方法,偶尔会报错:RecursionError: maximum recursion depth exceeded while calling a Python object
# less_array, grater_array = [], []
# for num in array:
# if num <= pivot:
# less_array.append(num)
# else:
# grater_array.append(num)
return quick_sort(less_array) + [pivot] + quick_sort(grater_array)
排序算法整理(Python实现)的更多相关文章
- 常用排序算法的python实现和性能分析
常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...
- 八大排序算法的 Python 实现
转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个 ...
- (排序算法整理)NEFU 30/32
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/caihongshijie6/article/details/26165093 事实上, ...
- 十大经典排序算法总结 (Python)
作业部落:https://www.zybuluo.com/listenviolet/note/1399285 以上链接是自己在作业部落编辑的排序算法总结- Github: https://github ...
- 一些排序算法的Python实现
''' Created on 2016/12/16 Created by freeol.cn 一些排序算法的Python实现 @author: 拽拽绅士 ''' '''值交换''' def swap( ...
- 排序算法整理C++(初赛)
排序算法整理 常见考点 将一个乱掉的字符串排回有序(以交换为基本操作)的最少操作,就是冒泡排序. 排序算法的稳定性 排序算法的时间复杂度 排序算法的稳定性 稳定性是指排序前两个元素a1 = a2,a1 ...
- 常见排序算法整理(python实现 持续更新)
1 快速排序 快速排序是对冒泡排序的一种改进. 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行 ...
- 【Python】常用排序算法的python实现和性能分析
作者:waterxi 原文链接 背景 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整 ...
- 面试中常用排序算法的python实现和性能分析
这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...
- 基本排序算法的Python实现
本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序.希望大家回顾知识的时候也能从我的这篇文章得到帮助. 为了防止误导读者,本文所有概念性 ...
随机推荐
- Teradata 数据库
笔者大学所学计算机专业,读书时接触过Oracle.mysql和SQL SERVER,一度坐井观天觉得数据库应该也就这些了,但自笔者毕业进入数据仓库这个行业,接触的第一个商业数据库即是Teradata, ...
- ppt和pptx转图片完整代码,解决2003版和2007版中文乱码问题
引入所需依赖,注意poi版本,新版本不支持,最好使用和我一样的版本. <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --& ...
- Codeforces 1340B Nastya and Scoreboard(dp,贪心)
题目链接OvO 题目大意 给你\(n\)串数字,\(1\)代表该位置是亮的,\(0\)代表是灭的.你必须修改\(k\)个数字,使某些\(0\)变为\(1\).注意,只能把原来的\(0\)改成\(1 ...
- Spring Cloud 系列之 Sleuth 链路追踪(三)
本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Sleuth 链路追踪(一) Spring Cloud 系列之 Sleuth 链路追踪(二) 本篇文章讲解 Sleu ...
- php 全局变量和超全局变量
global 全局变量(在当前页面全部地方有效) $GLOBALS['name'] 超全局变量(在整个网站全部地方有效) 一个包含了全部变量的全局组合数组.变量的名字就是数组的键.还有_GET,_PO ...
- centos 服务器上部署 xxl-job 通过 feign 访问 eureka 上注册的 service timeout
部署方式 1.使用 jar 包部署 出现的问题 1.通过 feign 调用其他服务,出现超时的问题,该问题不是 ribbon.hystrix 没有配置导致的超时,经过测试,即使配置了也没有作用,该方法 ...
- Hexo博客插入图片的方法
Hexo博客插入图片的方法 hexo图片blog hexo blog 插入图片的方法总结 hexo 的blog 内容是根据 markdown 文件的内容生成的html文件, 生成的文件全部在 /pub ...
- vue2.x学习笔记(三十二)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12684060.html. 深入响应式原理 vue最独特的特性之一,是其非侵入式(耦合度低)的响应式系统:数据模型仅 ...
- Redis介绍及字符串操作
一.前言 不同程序之间实现通信的方法? A.通过不同程序之间建立socket,实现通信.实际应用适用于使用broker,如RabbitMQ,ZeroMQ. B.通过Json,Pickle,利用文件的写 ...
- 15个 MySQL 基础面试题,DBA 们准备好了吗?
此前我们已经有发表过Linux 面试基础问答之一.二和三共3篇文章,获得读者的好评,同时我们得到反馈,有些读者希望这种交互式学习方法能够做得更加灵活.心动不如行动,我们这就为您奉上 15个 MySQL ...