本系列文章通过 1000(一篇文章表示 1 个实例) 个实例 ,为读者提供较为详细的练习题目,以便读者举一反三,深度学习。本系列的文章涉及到 Python 知识点包括:Python 语言基础、运算符和表达式、语句和程序结构、列表和元组、字典和集合、字符串、正则表达式、函数、面向对象编程、模块和包、异常处理和程序调试、文件和目录操作、数据库编程、界面编程、网络编程、WEB 编程、进程和线程、网络爬虫、游戏编程等知识点,由易到难,由浅入深,一步步打下坚实的编程基础。
本系列文章涉及的算法包括搜索、回溯、递归、排序、迭代、贪心、分治和动态规划等,涉及的数据结构包括字符串、列表、指针、区间、队列、矩阵、堆栈、链表、哈希表、线段树、二叉树、二叉搜索树和图结构等。
本系列文章是笔者为适应当前教育改革的创新要求,更好地践行语言类课程,满足实践教学与创新能力培养的需要,阅读大量书籍、各大互联网公司的面试算法、LintCode、LeetCode、九章算法和结合笔者近几年项目经验编写的系列文章,精选了 1000 个趣味性、实用性强的应用实例,从不同难度、不同算法、不同类型和不同数据结构等方面,将实际算法进行总结,希望为 Python 编程人员抛砖引玉。由于笔者经验与水平有限,博文中疏漏及不妥之处在所难免,衷心地希望各位读者在评论区多提宝贵意见及具体的修改建议,以便笔者进一步修改和完善。
一、快速排序法
快速排序法又称为分割交换法,它是冒泡排序法的一种改进。它的基本思想是:先在数据中找一个虚拟的中间值,并按此中间值将所有打算排序的数据分为两部分。其中,小于中间值的数据放在左边,大于中间值的数据放在右边,再用同样的方式处理左、右两边的数据,直到排序完成。操作的步骤如下:
假设有n项数据,数据值 用K1,K2,…,Kn 来表示。
- 先在数据中假设一个虚拟中间值K(为了方便,一般取第一个位置上的数)。
- 从左向右查找数据Ki,使得Ki>K,Ki的位置数记为i。
- 从右向左查找数据Kj,使得Kj<K,Kj的位置数记为j。
- 若i<j,那么数据Ki与Kj交换,并回到步骤(2)、(3)。
- 若i≥j,那么数据K与Kj交换,并以j为基准点分割成左右两部分,然后针对左右两部分再进行步骤1~步骤5,直到左半边数据等于右半边数据为止。
快速排序法最后的结果也有两种形式,即递增数列和递减数列。接下来通过一组数据来演示快速排序法的排序原理。例如,有这样一组数据:6,1,2,7,9,3,4,5,10,8,如下图所示:
按照递增进行排序,步骤如下:
步骤1:取原始值的第一个数6为虚拟中间值,即K=6;然后从左向右查找值大于6的数,即数值7,位置为i,即i=4;再从右向左查找值小于6的数,即数值5,位置是j,即j=8,如下图所示:
步骤2:i<j,因此交换Ki(数值7)和Kj(数值5)的位置,完成第一次排序结果。然后再从左向右查找值大于6的数,即数值9,位置为i,即i=5;再从右向左查找值小于6的数,即数值4,位置为j,即j=7,如下图所示:
步骤3:i<j,因此交换Ki(数值9)和Kj(数值4)的位置,完成第二次排序。然后再从左向右查找值大于6的数,即数值9,位置为i,即i=7;再从右向左查找值小于6的数,即数值3,位置是j,即j=6,如下图所示:
步骤4:i>j,因此交换虚拟中间值K(数值6)和Kj(数值3)的位置,完成第三次排序。此时,发现6的左半边都是小于6的数,右半边都是大于6的数,虚拟中间值6变成了真正的中间值,如下图所示:
步骤5:对中间值6的左半边数据进行排序,中间值和右半边数据暂时可以忽略。在左半边取虚拟中间值K=3,从左向右查找大于3的值,即数值5,位置为i,即i=4;再从右向左查找小于3的值,即数值2,位置为j,即j=3。如下图所示:
步骤6:i>j,因此需要交换K(数值3)和Kj(数值2)的值,如下图所示。此时虚拟中间值变成了真正的中间值。小于3的都在中间值3的左半边,大于3的都在中间值3的右半边。
步骤7:接下来对中间值为3的左、右两侧排序,经过排序之后,最终排序结果如下图所示:
步骤8:此时,整组数据的左半边已经完成排序,接下来对右半边进行排序,这次忽略已经排序好的左半边和中间值6。取右半边第一个位置的数为虚拟中间值K(数值9),然后从左向右找大于9的值,即数值10,位置为i,即i=9;再从右向左找小于9的值,即数值8,位置为j,即j=10。如下图所示:
步骤9:i<j,因此交换Ki(数值10)和Kj(数值8)的位置。然后再从左向右查找大于9的值,即数值10,位置为i,即i=10;再从右向左找小于9的值,即数值8,位置为j,即j=9。如下图所示:
步骤10:i>j,因此交换Kj(数值8)和虚拟中间值(数值9)的值,此时,虚拟中间值变成为真正的中间值,如下图所示:
步骤11:以中间值为9的左右两侧进行排序,最后完成右半边排序,如下图所示:
结合左半边排序和右半边排序,最终的结果如下图所示:
至此,完成排序。
二、实例:使用快速排序法进行递增排序
使用快速排序法为列表:6,1,2,7,9,3,4,5,10,8,进行递增排序。具体代码如下:
def quick(data, start, end): # 定义快速排序法函数
if start > end: # 如果开始值大于结束值
return # 直接退出程序
i, j = start, end
result = data[start] # 取虚拟中间值
while True: # 循环
while j > i and data[j] >= result: # 从右向左找,找到的数比虚拟中间值小就停止循环
j = j - 1 # 从右向左找,位置每次-1
while i < j and data[i] <= result: # 从左向右找,找到的数比虚拟中间值大就停止循环
i += 1 # 从左向右找,位置每次+1
if i < j: # i和j都停止,找到对应的位置,判断i<j
data[i], data[j] = data[j], data[i] # 交换位置i和j对应的数值
elif i >= j: # 判断i>=j
# 交换虚拟中间值和j位置上的数,此时虚拟中间值变成真正中间值
data[start], data[j] = data[j], data[start]
break # 完成第一次排序,此时以中间值分左右两侧
quick(data, start, i - 1) # 调用快速排序函数,再快速排序左半边数据
quick(data, i + 1, end) # 调用快速排序函数,再快速排序右半边数据
data = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8] # 定义列表并初始化
print("原始数据为:")
print(data) # 输出原始数据
print("--------------------------------")
quick(data, 0, (len(data) - 1)) # 调用快速排序,数据从位置0开始,到数据长度-1为止
print("排序之后的数据为:")
print(data) # 输出排序后数据
print("--------------------------------")
程序运行结果如图所示:
三、练习:入职年限排名
例如,某公司的6名职员入职年限分别是:1,3,15,20,5,4。利用快速排序法给这些职员入职年限按照从高到低顺序排序,具体代码如下:
def quick(data, start, end): # 定义快速排序法函数
if start > end: # 如果开始值大于结束值
return # 直接退出程序
i, j = start, end
result = data[start] # 取虚拟中间值
while True: # 循环
while j > i and data[j] <= result: # 从右向左找,找到的数虚拟中间值大就停止循环
j = j - 1 # 从右向左找,位置每次-1
while i < j and data[i] >= result: # 从左向右找,找到的数虚拟中间值小就停止循环
i += 1 # 从左向右找,位置每次+1
if i < j: # i和j都停止,找到对应的位置,判断i<j
data[i], data[j] = data[j], data[i] # 交换位置i和j对应的数值
elif i >= j: # 判断i>=j
# 交换虚拟中间值和j位置上的数,此时虚拟中间值变成真正中间值
data[start], data[j] = data[j], data[start]
break # 完成第一次排序,此时以中间值分左右两侧
quick(data, start, i - 1) # 调用快速排序函数,再快速排序左半边数据
quick(data, i + 1, end) # 调用快速排序函数,再快速排序右半边数据
data = [1, 3, 15, 20, 5, 4] # 定义列表并初始化
print("六名职员入职年限如下:")
print(data) # 输出原始数据
print("→→→→→→→→→→→→→→→→→→→→→")
quick(data, 0, (len(data) - 1)) # 调用快速排序,数据从位置0开始,到数据长度-1为止
print("从高到低排序之后的入职年限如下:")
print(data) # 输出排序后数据
print("→→→→→→→→→→→→→→→→→→→→→")
程序运行结果如图所示:
感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!
好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请点赞
、评论
、收藏
一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注
我哦!
转载:https://blog.csdn.net/xw1680/article/details/115986606