Python实现的数据结构与算法之快速排序详解
作者:RussellLuo 发布时间:2022-03-03 16:49:17
标签:Python,快速排序
本文实例讲述了Python实现的数据结构与算法之快速排序。分享给大家供大家参考。具体分析如下:
一、概述
快速排序(quick sort)是一种分治排序算法。该算法首先 选取 一个划分元素(partition element,有时又称为pivot);接着重排列表将其 划分 为三个部分:left(小于划分元素pivot的部分)、划分元素pivot、right(大于划分元素pivot的部分),此时,划分元素pivot已经在列表的最终位置上;然后分别对left和right两个部分进行 递归排序。
其中,划分元素的 选取 直接影响到快速排序算法的效率,通常选择列表的第一个元素或者中间元素或者最后一个元素作为划分元素,当然也有更复杂的选择方式;划分 过程根据划分元素重排列表,是快速排序算法的关键所在,该过程的原理示意图如下:
<-- 选取划分元素 -->
<-- 划分过程 -->
<-- 划分结果 -->
快速排序算法的优点是:原位排序(只使用很小的辅助栈),平均情况下的时间复杂度为 O(n log n)。快速排序算法的缺点是:它是不稳定的排序算法,最坏情况下的时间复杂度为 O(n2)。
二、Python实现
1、标准实现
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def stdQuicksort(L):
qsort(L, 0, len(L) - 1)
def qsort(L, first, last):
if first < last:
split = partition(L, first, last)
qsort(L, first, split - 1)
qsort(L, split + 1, last)
def partition(L, first, last):
# 选取列表中的第一个元素作为划分元素
pivot = L[first]
leftmark = first + 1
rightmark = last
while True:
while L[leftmark] <= pivot:
# 如果列表中存在与划分元素pivot相等的元素,让它位于left部分
# 以下检测用于划分元素pivot是列表中的最大元素时,
#防止leftmark越界
if leftmark == rightmark:
break
leftmark += 1
while L[rightmark] > pivot:
# 这里不需要检测,划分元素pivot是列表中的最小元素时,
# rightmark会自动停在first处
rightmark -= 1
if leftmark < rightmark:
# 此时,leftmark处的元素大于pivot,
#而rightmark处的元素小于等于pivot,交换二者
L[leftmark], L[rightmark] = L[rightmark], L[leftmark]
else:
break
# 交换first处的划分元素与rightmark处的元素
L[first], L[rightmark] = L[rightmark], L[first]
# 返回划分元素pivot的最终位置
return rightmark
2、Pythonic实现
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def pycQuicksort(L):
if len(L) <= 1: return L
return pycQuicksort([x for x in L if x < L[0]]) + \
[x for x in L if x == L[0]] + \
pycQuicksort([x for x in L if x > L[0]])
对比 标准实现 可以看出,Pythonic实现 更简洁、更直观、更酷。但需要指出的是,Pythonic实现 使用了Python中的 列表解析 (List Comprehension,也叫列表展开、列表推导),每一次 递归排序 都会产生新的列表,因此失去了快速排序算法本来的 原位排序 的优点。
三、算法测试
#!/usr/bin/env python
# -*- coding: utf-8 -*-
if __name__ == '__main__':
L = [54, 26, 93, 17, 77, 31, 44, 55, 20]
M = L[:]
print('before stdQuicksort: ' + str(L))
stdQuicksort(L)
print('after stdQuicksort: ' + str(L))
print('before pycQuicksort: ' + str(M))
print('after pycQuicksort: ' + str(pycQuicksort(M)))
运行结果:
$ python testquicksort.py
before stdQuicksort: [54, 26, 93, 17, 77, 31, 44, 55, 20]
after stdQuicksort: [17, 20, 26, 31, 44, 54, 55, 77, 93]
before pycQuicksort: [54, 26, 93, 17, 77, 31, 44, 55, 20]
after pycQuicksort: [17, 20, 26, 31, 44, 54, 55, 77, 93]
希望本文所述对大家的Python程序设计有所帮助。


猜你喜欢
- 前言最近组长安排着做一个项目,h5的应用下载项目,想着做起来还是比较容易,可是看到提出的需求,我就有点懵逼了!需要对应用的下载进行统计!!!
- 本文给大家介绍如何判断表单验证的实例代码,在没给大家介绍正文之前,先给大家介绍下插件。插件介绍先上一个图:下载地址:https://gith
- Array(数组)内部机制在 Go 语言中数组是固定长度的数据类型,它包含相同类型的连续的元素,这些元素可以是内建类型,像数字和字符串,也可
- 游戏玩法根据神庙逃亡,实现一个人躲避僵尸的小游戏,主要的是精灵、精灵组之间相撞、相交的处理。游戏开始随机出现一定的僵尸,随机移动,玩家在一位
- 最近写一个和二维列表有关的算法时候发现的当用max求二维列表中最大值时,输出的结果是子列表首元素最大的那个列表测试如下c=[[1,2,-1]
- 24小时内记录(即86400秒)$sql="Select video_id,count(id)as n FROM `rec_dow
- 通过锁机制,可以实现多线程同时对某个表进行操作。如下图所示,在某个时刻,用户甲、用户乙、用户丙可能会同时或者先后(前面一个作业还没有完成)对
- Sql Server中清空所有数据表中的记录清空所有数据表中的记录:exec sp_msforeachtable @Comman
- 1. 日志输出到屏幕#!/usr/bin/env python# -*- coding: utf-8 -*-from __future__
- 以下各种方式仅供参考,本人亲测只有官方提供的方式比较靠谱。1. 使用多个进程启动多个Tornado实例import tornado.http
- 介绍在本文中,云朵君将和大家一起了解装饰器的工作原理,如何将我们之前定义的定时器类 Timer 扩展为装饰器,以及如何简化计时功能。最后对
- 首先说说框架(Frameworks)这个词,框架就是为我们提供了一个平台一个运行环境,在如此统一的前提下我们做相关开发才能“有章可循”,要充
- 前言:Event在python线程间同步是一种常用的方法,本博客以生产者线程和工作者线程为例说明Event在线程间进行10次同步的应用。im
- 1、说明Tasks用于并发调度协程,通过asyncio.create_task(协程对象)创建Task对象,使协程能够加入事件循环,等待调度
- 本文实例为大家分享了python实现批量格式转换的具体代码,供大家参考,具体内容如下深度学习过程中总是绕不开数据集的制作,有时候实际图片格式
- 1,新建一个项目File --> New Project...2,新建一个文件右键单击刚建好的helloWord项目,选择New --
- 本文实例讲述了python自动化测试之从命令行运行测试用例with verbosity,分享给大家供大家参考。具体如下:实例文件recipe
- 本文实例为大家分享了python实现简单颜色识别程序的具体代码,供大家参考,具体内容如下import numpy as npimport c
- 使用JdbcTemplate的步骤1、设置spring-jdbc和spring-tx的坐标(也就是导入依赖) <depen
- 一套javascript摇奖程序,随机6+1选号码,类似游戏彩票摇奖效果,实时滚动。截图:<style>.inp{ width: