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实现代码统计工具(终极篇)
Jul 04 Python
Python实现的手机号归属地相关信息查询功能示例
Jun 08 Python
基于Python3 逗号代码 和 字符图网格(详谈)
Jun 22 Python
Python使用cx_Oracle模块操作Oracle数据库详解
May 07 Python
实例讲解python中的协程
Oct 08 Python
Python 脚本获取ES 存储容量的实例
Dec 27 Python
Python离线安装PIL 模块的方法
Jan 08 Python
Python按钮的响应事件详解
Mar 04 Python
Python中的引用知识点总结
May 20 Python
python 实现创建文件夹和创建日志文件的方法
Jul 07 Python
利用django model save方法对未更改的字段依然进行了保存
Mar 28 Python
如何利用Python 进行边缘检测
Oct 14 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入门
2006/10/09 PHP
PHP错误机制知识汇总
2016/03/24 PHP
php简单计算年龄的方法(周岁与虚岁)
2016/12/06 PHP
PHP封装curl的调用接口及常用函数详解
2018/05/31 PHP
基于jquery点击自以外任意处,关闭自身的代码
2012/02/10 Javascript
检测input每次的输入是否合法遇到汉字输入就有问题
2012/05/23 Javascript
基于jquery的文章中所有图片width大小批量设置方法
2013/08/01 Javascript
js与jquery获取父元素,删除子元素的两种不同方法
2014/01/09 Javascript
jquery禁止输入数字以外的字符的示例(纯数字验证码)
2014/04/10 Javascript
第五篇Bootstrap 排版
2016/06/21 Javascript
jquery操作ID带有变量的节点实例
2016/12/07 Javascript
利用jQuery.Validate异步验证用户名是否存在(推荐)
2016/12/09 Javascript
JS仿京东移动端手指拨动切换轮播图效果
2020/04/10 Javascript
js基于myFocus实现轮播图效果
2017/02/14 Javascript
基于javascript的异步编程实例详解
2017/04/10 Javascript
关于Google发布的JavaScript代码规范你要知道哪些
2018/04/04 Javascript
JS去除字符串最后的逗号实例分析【四种方法】
2019/06/20 Javascript
解决vue.js提交数组时出现数组下标的问题
2019/11/05 Javascript
解决vue的router组件component在import时不能使用变量问题
2020/07/26 Javascript
javascript实现移动端触屏拖拽功能
2020/07/29 Javascript
js对象属性名驼峰式转下划线的实例代码
2020/09/17 Javascript
解决antd日期选择组件,添加value就无法点击下一年和下一月问题
2020/10/29 Javascript
跟老齐学Python之不要红头文件(2)
2014/09/28 Python
Python中实现三目运算的方法
2015/06/21 Python
Python函数式编程指南(四):生成器详解
2015/06/24 Python
举例讲解Python中的身份运算符的使用方法
2015/10/13 Python
python字典改变value值方法总结
2019/06/21 Python
Python实现CAN报文转换工具教程
2020/05/05 Python
python实现启动一个外部程序,并且不阻塞当前进程
2020/12/05 Python
html5读取本地文件示例代码
2014/04/22 HTML / CSS
Rowdy Gentleman服装和配饰:美好时光
2019/09/24 全球购物
乌克兰移动电子产品和相关配件的在线商店:iTMag
2020/03/16 全球购物
四年大学生活的个人自我评价
2013/12/11 职场文书
建筑工程技术专业求职信
2014/07/16 职场文书
房产公证委托书范本
2014/09/20 职场文书
2015年七夕情人节感言
2015/08/03 职场文书