python实现八大排序算法(2)


Posted in Python onSeptember 14, 2017

本文接上一篇博客python实现的八大排序算法part1,将继续使用python实现八大排序算法中的剩余四个:快速排序、堆排序、归并排序、基数排序

5、快速排序

快速排序是通常被认为在同数量级(O(nlog2n))的排序方法中平均性能最好的。

算法思想:

已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先任取数据a[x]作为基准。比较a[x]与其它数据并排序,使a[x]排在数据的第k位,并且使a[1]~a[k-1]中的每一个数据<a[x],a[k+1]~a[n]中的每一个数据>a[x],然后采用分治的策略分别对a[1]~a[k-1]和a[k+1]~a[n]两组数据进行快速排序。
优点:极快,数据移动少;
缺点:不稳定。

python代码实现:

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

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

#!/usr/bin/env python
#coding:utf-8
'''
file:python-8sort.py
date:9/1/17 9:03 AM
author:lockey
email:lockey@123.com
desc:python实现八大排序算法
'''
lst = [65,568,9,23,4,34,65,8,6,9]
def quick_sort(list):
  if len(list) <= 1:
    return list
  else:
    pivot = list[0]
    return quick_sort([x for x in list[1:] if x < pivot]) + \
        [pivot] + \
        quick_sort([x for x in list[1:] if x >= pivot])

运行测试结果截图:

python实现八大排序算法(2)

好吧,还有更精简的语法糖,一行完事:

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

若初始序列按关键码有序或基本有序时,快排序反而蜕化为冒泡排序。为改进之,通常以“三者取中法”来选取基准记录,即将排序区间的两个端点与中点三个记录关键码居中的调整为支点记录。快速排序是一个不稳定的排序方法。

在改进算法中,我们将只对长度大于k的子序列递归调用快速排序,让原序列基本有序,然后再对整个基本有序序列用插入排序算法排序。实践证明,改进后的算法时间复杂度有所降低,且当k取值为 8 左右时,改进算法的性能最佳。

6、堆排序(Heap Sort)

堆排序是一种树形选择排序,是对直接选择排序的有效改进。

优点 : 效率高
缺点:不稳定

堆的定义下:具有n个元素的序列 (h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1) (i=1,2,...,n/2)时称之为堆。在这里只讨论满足前者条件的堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项(大顶堆)。完全二 叉树可以很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。

算法思想:

初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个 堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对 它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。

python代码实现:

# -*- coding: UTF-8 -*-
'''
Created on 2017年9月2日
Running environment:win7.x86_64 eclipse python3
@author: Lockey
'''
lst = [65,568,9,23,4,34,65,8,6,9]
def adjust_heap(lists, i, size):# 调整堆
  lchild = 2 * i + 1;rchild = 2 * i + 2
  max = i
  if i < size / 2:
    if lchild < size and lists[lchild] > lists[max]:
      max = lchild
    if rchild < size and lists[rchild] > lists[max]:
      max = rchild
    if max != i:
      lists[max], lists[i] = lists[i], lists[max]
      adjust_heap(lists, max, size)
def build_heap(lists, size):# 创建堆
  halfsize = int(size/2)
  for i in range(0, halfsize)[::-1]:
    adjust_heap(lists, i, size)
def heap_sort(lists):# 堆排序
  size = len(lists)
  build_heap(lists, size)
  for i in range(0, size)[::-1]:
    lists[0], lists[i] = lists[i], lists[0]
    adjust_heap(lists, 0, i)
    print(lists)

结果示例:

python实现八大排序算法(2)

7、归并排序

算法思想:

归并(Merge)排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

# -*- coding: UTF-8 -*-
'''
Created on 2017年9月2日
Running environment:win7.x86_64 eclipse python3
@author: Lockey
'''
lst = [65,568,9,23,4,34,65,8,6,9]
def merge(left, right):
  i, j = 0, 0
  result = []
  while i < len(left) and j < len(right):
    if left[i] <= right[j]:
      result.append(left[i])
      i += 1
    else:
      result.append(right[j])
      j += 1
  result += left[i:]
  result += right[j:]
  print(result)
  return result
def merge_sort(lists):# 归并排序
  if len(lists) <= 1:
    return lists
  num = int(len(lists) / 2)
  left = merge_sort(lists[:num])
  right = merge_sort(lists[num:])
  return merge(left, right)

程序结果示例:

python实现八大排序算法(2)

8、桶排序/基数排序(Radix Sort)

优点:快,效率最好能达到O(1)
缺点:

1.首先是空间复杂度比较高,需要的额外开销大。排序有两个数组的空间开销,一个存放待排序数组,一个就是所谓的桶,比如待排序值是从0到m-1,那就需要m个桶,这个桶数组就要至少m个空间。

2.其次待排序的元素都要在一定的范围内等等。

算法思想:

是将阵列分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的阵列内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
简单来说,就是把数据分组,放在一个个的桶中,然后对每个桶里面的在进行排序。
例如要对大小为[1..1000]范围内的n个整数A[1..n]排序

首先,可以把桶大小设为10,这样就有100个桶了,具体而言,设集合B[1]存储[1..10]的整数,集合B[2]存储 (10..20]的整数,……集合B[i]存储( (i-1)*10, i*10]的整数,i = 1,2,..100。总共有 100个桶。

然后,对A[1..n]从头到尾扫描一遍,把每个A[i]放入对应的桶B[j]中。 再对这100个桶中每个桶里的数字排序,这时可用冒泡,选择,乃至快排,一般来说任 何排序法都可以。

最后,依次输出每个桶里面的数字,且每个桶中的数字从小到大输出,这 样就得到所有数字排好序的一个序列了。

假设有n个数字,有m个桶,如果数字是平均分布的,则每个桶里面平均有n/m个数字。如果

对每个桶中的数字采用快速排序,那么整个算法的复杂度是

O(n + m * n/m*log(n/m)) = O(n + nlogn - nlogm)

从上式看出,当m接近n的时候,桶排序复杂度接近O(n)

当然,以上复杂度的计算是基于输入的n个数字是平均分布这个假设的。这个假设是很强的 ,实际应用中效果并没有这么好。如果所有的数字都落在同一个桶中,那就退化成一般的排序了。

python代码实现:

# -*- coding: UTF-8 -*-
'''
Created on 2017年9月2日
Running environment:win7.x86_64 eclipse python3
@author: Lockey
'''
import math
lst = [65,56,9,23,84,34,8,6,9,54,11]
#因为列表数据范围在100以内,所以将使用十个桶来进行排序
def radix_sort(lists, radix=10):
  k = int(math.ceil(math.log(max(lists), radix)))
  bucket = [[] for i in range(radix)]
  for i in range(1, k+1):
    for j in lists:
      gg = int(j/(radix**(i-1))) % (radix**i)
      bucket[gg].append(j)
    del lists[:]
    for z in bucket:
      lists += z
      del z[:]
      print(lists)
  return lists

程序运行测试结果:

python实现八大排序算法(2)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python matplotlib 画图窗口显示到gui或者控制台的实例
May 24 Python
用Django写天气预报查询网站
Oct 21 Python
Python 正则表达式匹配字符串中的http链接方法
Dec 25 Python
Python3.5面向对象与继承图文实例详解
Apr 24 Python
Python3.5常见内置方法参数用法实例详解
Apr 29 Python
python 中值滤波,椒盐去噪,图片增强实例
Dec 18 Python
python实现的批量分析xml标签中各个类别个数功能示例
Dec 30 Python
python global和nonlocal用法解析
Feb 03 Python
openCV提取图像中的矩形区域
Jul 21 Python
Python 列表反转显示的四种方法
Nov 16 Python
Python还能这么玩之用Python修改了班花的开机密码
Jun 04 Python
python利用while求100内的整数和方式
Nov 07 Python
Python3.4编程实现简单抓取爬虫功能示例
Sep 14 #Python
python实现八大排序算法(1)
Sep 14 #Python
python实现简单聊天应用 python群聊和点对点均实现
Sep 14 #Python
Python实现购物系统(示例讲解)
Sep 13 #Python
python模块之sys模块和序列化模块(实例讲解)
Sep 13 #Python
python模块之time模块(实例讲解)
Sep 13 #Python
python difflib模块示例讲解
Sep 13 #Python
You might like
php 小乘法表实现代码
2009/07/16 PHP
php出现内存位置访问无效错误问题解决方法
2014/08/16 PHP
让getElementsByName适应IE和firefox的方法
2007/09/24 Javascript
jquery 弹出层实现代码
2009/10/30 Javascript
去掉gridPanel表头全选框的小例子
2013/07/18 Javascript
将字符串中由空格隔开的每个单词首字母大写
2014/04/06 Javascript
Javascript仿PHP $_GET获取URL中的参数
2014/05/12 Javascript
谷歌浏览器不支持showModalDialog模态对话框的解决方法
2014/09/22 Javascript
超实用的JavaScript表单代码段
2016/02/26 Javascript
Bootstrap Chart组件使用教程
2016/04/28 Javascript
JavaScript开发Chrome浏览器扩展程序UI的教程
2016/05/16 Javascript
JS简单实现点击按钮或文字显示遮罩层的方法
2017/04/27 Javascript
基于js中的原型(全面讲解)
2017/09/19 Javascript
vue的传参方式汇总和router使用技巧
2018/05/22 Javascript
解决Angularjs异步操作后台请求用$q.all排列先后顺序问题
2019/11/29 Javascript
Postman参数化实现过程及原理解析
2020/08/13 Javascript
[01:37]TI4西雅图DOTA2前线报道 VG拿下首胜教练357给出获胜秘诀
2014/07/10 DOTA
归纳整理Python中的控制流语句的知识点
2015/04/14 Python
Python正则抓取新闻标题和链接的方法示例
2017/04/24 Python
分享几道你可能遇到的python面试题
2017/07/24 Python
tf.truncated_normal与tf.random_normal的详细用法
2018/03/05 Python
Python代码打开本地.mp4格式文件的方法
2019/01/03 Python
Django用户认证系统 User对象解析
2019/08/02 Python
Python实现元素等待代码实例
2019/11/11 Python
Python线程指南分享
2019/11/19 Python
wxPython实现画图板
2020/08/27 Python
Python插入Elasticsearch操作方法解析
2020/01/19 Python
PyCharm2020.1.1与Python3.7.7的安装教程图文详解
2020/08/07 Python
JupyterNotebook 输出窗口的显示效果调整实现
2020/09/22 Python
CSS3 实现footer 固定在底部(无论页面多高始终在底部)
2019/10/15 HTML / CSS
美国便宜的横幅和标志印刷在线:Best of Signs
2019/05/29 全球购物
企业年会主持词
2014/03/27 职场文书
2015年清明节网上祭英烈活动总结
2015/03/26 职场文书
2016大学生社会实践心得体会范文
2016/01/14 职场文书
MySQL单表千万级数据处理的思路分享
2021/06/05 MySQL
Redis基本数据类型哈希Hash常用操作命令
2022/06/01 Redis