本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序。希望大家回顾知识的时候也能从我的这篇文章得到帮助。

为了防止误导读者,本文所有概念性内容均截取自对应Wiki

冒泡排序

原理

冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

步骤

冒泡排序算法的运作如下:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

代码

def bubble_sort(list):
length = len(list)
# 第一级遍历
for index in range(length):
# 第二级遍历
for j in range(1, length - index):
if list[j - 1] > list[j]:
# 交换两者数据,这里没用temp是因为python 特性元组。
list[j - 1], list[j] = list[j], list[j - 1]
return list

这种排序其实还可以稍微优化一下,添加一个标记,在排序已完成时,停止排序。

def bubble_sort_flag(list):
length = len(list)
for index in range(length):
# 标志位
flag = True
for j in range(1, length - index):
if list[j - 1] > list[j]:
list[j - 1], list[j] = list[j], list[j - 1]
flag = False
if flag:
# 没有发生交换,直接返回list
return list
return list

选择排序

原理

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理大致是将后面的元素最小元素一个个取出然后按顺序放置。

步骤

  1. 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,

  2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

  3. 重复第二步,直到所有元素均排序完毕。

代码

def selection_sort(list):
n=len(list)
for i in range (0,n):
min = i
for j in range(i+1,n):
if list[j]<list[min]:
min=j
list[min],list[i]=list[i],list[min]
return list

插入排序

原理

插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

步骤

  1. 从第一个元素开始,该元素可以认为已经被排序

  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描

  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置

  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置

  5. 将新元素插入到该位置后

  6. 重复步骤2~5

代码

def insert_sort(list):
n = len(list)
for i in range(1, n):
# 后一个元素和前一个元素比较
# 如果比前一个小
if list[i] < list[i - 1]:
# 将这个数取出
temp = list[i]
# 保存下标
index = i
# 从后往前依次比较每个元素
for j in range(i - 1, -1, -1):
# 和比取出元素大的元素交换
if list[j] > temp:
list[j + 1] = list[j]
index = j
else:
break
# 插入元素
list[index] = temp
return list

希尔排序

原理

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率

但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

步骤

每次以一定步长(就是跳过等距的数)进行排序,直至步长为1.

代码

def shell_sort(list):
n = len(list)
# 初始步长
gap = round(n / 2)
while gap > 0:
for i in range(gap, n):
# 每个步长进行插入排序
temp = list[i]
j = i
# 插入排序
while j >= gap and list[j - gap] > temp:
list[j] = list[j - gap]
j -= gap
list[j] = temp
# 得到新的步长
gap = round(gap / 2)
return list

步长使用的是Donald Shell的建议,另外步长还可以使用Sedgewick提出的(1, 5, 19, 41, 109,...)。

也可以使用 斐波那契数列 除去0和1将剩余的数以黄金分区比的两倍的幂进行运算得到的数列。

归并排序

原理

归并操作(归并算法),指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。

步骤

迭代法

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

  4. 重复步骤3直到某一指针到达序列尾

  5. 将另一序列剩下的所有元素直接复制到合并序列尾

递归法

假设序列共有n个元素:

  1. 将序列每相邻两个数字进行归并操作,形成 {displaystyle floor(n/2)} floor(n/2)个序列,排序后每个序列包含两个元素

  2. 将上述序列再次归并,形成 {displaystyle floor(n/4)} floor(n/4)个序列,每个序列包含四个元素

  3. 重复步骤2,直到所有元素排序完毕

代码

# 递归法
def merge_sort(list):
# 认为长度不大于1的数列是有序的
if len(list) <= 1:
return list
# 二分列表
middle = len(list) // 2
left = merge_sort(list[:middle])
right = merge_sort(list[middle:])
# 最后一次合并
return merge(left, right)
# 合并
def merge(left, right):
l,r=0,0
result=[]
while l<len(left) and r<len(right):
if left[l] <right[r]:
result.append(left[l])
l+=1
else:
result.append(right[r])
r +=1
reslut +=left[l:]
result+=right[r:]
return result

鄙人不才,不知归并排序的迭代法如何用Python实现,望指教。

快速排序

原理

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。

步骤

  1. 从数列中挑出一个元素,称为"基准"(pivot),

  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

代码

普通版

def quick_sort(list):
less = []
pivotList = []
more = []
# 递归出口
if len(list) <= 1:
return list
else:
# 将第一个值做为基准
pivot = list[0]
for i in list:
# 将比急转小的值放到less数列
if i < pivot:
less.append(i)
# 将比基准打的值放到more数列
elif i > pivot:
more.append(i)
# 将和基准相同的值保存在基准数列
else:
pivotList.append(i)
# 对less数列和more数列继续进行排序
less = quick_sort(less)
more = quick_sort(more)
return less + pivotList + more

咳咳,下面这段代码出自《Python cookbook 第二版》传说中的三行实现python快速排序。

def qsort(arr):
if len(arr) <= 1:
return arr
else:
pivot = arr[0]
return qsort([x for x in arr[1:] if x < pivot]) + \
[pivot] + \
qsort([x for x in arr[1:] if x >= pivot])

当然还有一行语法糖版本:

qs = lambda xs : ( (len(xs) <= 1 and [xs]) or [ qs( [x for x in xs[1:] if x < xs[0]] ) + [xs[0]] + qs( [x for x in xs[1:] if x >= xs[0]] ) ] )[0]

是不是感受到了Python的魅力?

堆排序

原理

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

步骤

  1. 创建最大堆:将堆所有数据重新排序,使其成为最大堆

  2. 最大堆调整:作用是保持最大堆的性质,是创建最大堆的核心子程序

  3. 堆排序:移除位在第一个数据的根节点,并做最大堆调整的递归运算

代码

def heap_sort(list):
# 创建最大堆
for start in range((len(list) - 2) // 2, -1, -1):
sift_down(list, start, len(list) - 1) # 堆排序
for end in range(len(list) - 1, 0, -1):
list[0], list[end] = list[end], list[0]
sift_down(list, 0, end - 1)
return list # 最大堆调整
def sift_down(lst, start, end):
root = start
while True:
child = 2 * root + 1
if child > end:
break
if child + 1 <= end and lst[child] < lst[child + 1]:
child += 1
if lst[root] < lst[child]:
lst[root], lst[child] = lst[child], lst[root]
root = child
else:
break

计数排序

原理

当输入的元素是n个0到k之间的整数时,它的运行时间是Θ(n + k)。计数排序不是比较排序,排序的速度快于任何比较排序算法。

由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。例如:计数排序是用来排序0到100之间的数字的最好的算法,但是它不适合按字母顺序排序人名。但是,计数排序可以用在基数排序算法中,能够更有效的排序数据范围很大的数组。

步骤

  1. 找出待排序的数组中最大和最小的元素

  2. 统计数组中每个值为i的元素出现的次数,存入数组 C 的第 i 项

  3. 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)

  4. 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

代码

def count_sort(list):
min = 2147483647
max = 0
# 取得最大值和最小值
for x in list:
if x < min:
min = x
if x > max:
max = x
# 创建数组C
count = [0] * (max - min +1)
for index in list:
count[index - min] += 1
index = 0
# 填值
for a in range(max - min+1):
for c in range(count[a]):
list[index] = a + min
index += 1
return list

第九种排序

None?

当然不会

自然就是系统自带的

list.sort()

以上所有源代码均在 https://github.com/EINDEX/Python-algorithm/tree/master/Sort

基本排序算法的Python实现的更多相关文章

  1. 八大排序算法的 Python 实现

    转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个 ...

  2. 常用排序算法的python实现和性能分析

    常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...

  3. 十大经典排序算法总结 (Python)

    作业部落:https://www.zybuluo.com/listenviolet/note/1399285 以上链接是自己在作业部落编辑的排序算法总结- Github: https://github ...

  4. 一些排序算法的Python实现

    ''' Created on 2016/12/16 Created by freeol.cn 一些排序算法的Python实现 @author: 拽拽绅士 ''' '''值交换''' def swap( ...

  5. 经典排序算法及python实现

    今天我们来谈谈几种经典排序算法,然后用python来实现,最后通过数据来比较几个算法时间 选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据 ...

  6. python基础===八大排序算法的 Python 实现

    本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一 ...

  7. 八大排序算法---基于python

    本文节选自:http://python.jobbole.com/82270/ 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 ...

  8. 十大经典排序算法(python实现)(原创)

    个人最喜欢的排序方法是非比较类的计数排序,简单粗暴.专治花里胡哨!!! 使用场景: 1,空间复杂度 越低越好.n值较大: 堆排序 O(nlog2n) O(1) 2,无空间复杂度要求.n值较大: 桶排序 ...

  9. 十大经典排序算法的python实现

    十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序.包括:冒泡排序.选择排序.归并排序.快速 ...

随机推荐

  1. TFS online 自动部署配置

    概要 采用tfs online进行源码管理,并配置自动编译部署到外网上一台服务器上(阿里云虚拟机) 步骤; 下载angent,并运行脚本安装 配置release managemetn; 1)Copy ...

  2. Android 手机卫士--自定义属性

    在前面的文章中,已经实现了“设置中心”第一栏的功能以及布局 本文地址:http://www.cnblogs.com/wuyudong/p/5936016.html,转载请注明出处. 自定义属性声明 接 ...

  3. Git 简易手册

    前言 这里就不介绍 git 了,表一看到命令行就怕怕,常用的命令也就这些,基本满足 99% 以上的项目需求,非常实用. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnbl ...

  4. RelativeLayout的位置属性总结

    使用"@id/…"时,所写的id必须在上文中已经定义,不能使用在下文定义的id RelativeLayout的子控件属性总结—— 按照控件之间常规的上下左右依次排列:(指定控件ID ...

  5. asp.net signalR 专题—— 第四篇 模拟RPC模式的Hub操作

    在之前的文章中,我们使用的都是持久连接,但是使用持久连接的话,这种模拟socket的形式使用起来还是很不方便的,比如只有一个唯一的 OnReceived方法来处理业务逻辑,如下图: protected ...

  6. Java实现不同的WebService 调用方式

    请求过程分析: 1.使用get方式获取wsdl文件,称为握手 2.使用post发出请求 3.服务器响应成功 几种监听工具: http watch Web Service explorer eclips ...

  7. WinForm常用属性

    Text: 字符串,窗体标题 MaximizeBox: 布尔, 窗体能否最大化 MinimizeBox: 布尔,窗体能否最小化 ShowIcon: 布尔,左上角图标 ShowInTaskbar: 布尔 ...

  8. 一则uiautomation错误处理

    一款iphone程序,用到了多window,结果在最后一个window里设置textfield时出错 target.frontMostApp().mainWindow().textFields()[0 ...

  9. android 让一个Activity停留几秒后再跳转

    有时候我们需要在某个 Activity 停留几秒种,然后再跳到下一个 Activity.那么这个怎么实现呢? 一个方法是可以使用 Thread 的 sleep 函数,这个我们在 用Handler实现线 ...

  10. js鼠标滚轮事件

    不多说,直接上代码. //非ie document.body.onmousewheel = function(event) { event = event || window.event; conso ...