0

0

Python快速排序实现:常见错误与正确分区逻辑解析

碧海醫心

碧海醫心

发布时间:2025-10-29 11:40:32

|

393人浏览过

|

来源于php中文网

原创

Python快速排序实现:常见错误与正确分区逻辑解析

本文深入探讨了python快速排序算法的正确实现,重点分析了在分区(partitioning)过程中常见的逻辑错误,如交换操作的缩进问题、支点(pivot)的最终位置确定以及递归调用边界的设置。通过详细的代码示例和修正,旨在帮助开发者理解并构建一个健壮、高效的快速排序算法。

快速排序算法概述

快速排序(Quick Sort)是一种高效的、基于分治策略的排序算法。其核心思想是:

  1. 选择支点(Pivot):从待排序数组中选择一个元素作为“支点”(pivot)。
  2. 分区(Partition):将数组中所有小于支点的元素移到支点左边,所有大于支点的元素移到支点右边。这个操作完成后,支点就处于其最终的有序位置。
  3. 递归排序:对支点左右两边的子数组分别递归地执行快速排序。

当子数组只有一个元素或为空时,递归停止。

常见的快速排序实现陷阱与修正

在实现快速排序时,尤其是在分区逻辑部分,开发者常常会遇到一些细微但关键的错误,导致排序结果不正确。下面我们将结合一个常见的错误示例,分析并给出正确的实现。

原始代码中的问题分析

立即学习Python免费学习笔记(深入)”;

考虑以下一个尝试实现快速排序的Python代码片段:

Krea AI
Krea AI

多功能的一站式AI图像生成和编辑平台

下载
class QuickSort:
    def quickSort(self, list, low, high):
        if (low >= high):
            return 
        else:
            leftPointer = low
            rightPointer = high
            pivot = list[high]
            while (leftPointer < rightPointer):
                while (leftPointer < rightPointer and list[leftPointer] < pivot):
                    leftPointer += 1
                while (leftPointer < rightPointer and list[rightPointer] > pivot):
                    rightPointer -= 1
            list[leftPointer], list[rightPointer] = list[rightPointer], list[leftPointer] # 问题1:缩进错误
         list[high], list[leftPointer] = list[leftPointer], list[high] # 问题2:支点放置逻辑错误
         self.quickSort(list, low, rightPointer - 1) # 问题3:递归边界错误
         self.quickSort(list, rightPointer + 1, high) # 问题3:递归边界错误
       return list

这段代码存在以下几个主要问题:

  1. 交换操作的缩进错误:list[leftPointer], list[rightPointer] = list[rightPointer], list[leftPointer] 这行代码的缩进不正确,它应该在 while (leftPointer < rightPointer) 循环内部执行,以在每次找到需要交换的元素时进行交换。而原始代码将其放在循环外部,导致在整个分区过程中只执行一次交换。
  2. 支点放置逻辑错误:list[high], list[leftPointer] = list[leftPointer], list[high] 这行旨在将支点放到其最终位置。然而,当 leftPointer 最终指向的元素小于支点时,这个交换会导致支点被错误放置。正确的逻辑需要确保支点最终位于所有小于它的元素之后、所有大于它的元素之前。
  3. 递归调用边界错误:在分区完成后,rightPointer 并不总是支点最终的位置。正确的递归调用应该以支点最终的位置为界限,将数组分成两个子部分。在正确的实现中,leftPointer 最终会指向支点的新位置。

正确的快速排序实现

为了解决上述问题,我们需要对分区逻辑和支点放置策略进行调整。下面是修正后的Python快速排序实现:

class QuickSort:
    def quickSort(self, input_list, low, high):
        # 1. 基本情况:如果子数组只有一个元素或为空,则已排序
        if low >= high:
            return

        # 优化:处理两个元素的子数组且已排序的情况
        # 实际操作中,这个优化可以合并到low >= high的判断中,或者直接依赖后续逻辑
        # if high - low == 1 and input_list[low] <= input_list[high]:
        #     return

        # 2. 选择支点:这里选择最后一个元素作为支点
        pivot = input_list[high]

        # 初始化左右指针
        # leftPointer从low开始寻找大于pivot的元素
        # rightPointer从high-1开始寻找小于pivot的元素(不包括pivot本身)
        leftPointer = low
        rightPointer = high - 1

        # 3. 分区过程
        # 当leftPointer小于等于rightPointer时,继续进行分区
        while leftPointer <= rightPointer:
            # 找到第一个大于或等于pivot的元素
            while leftPointer <= rightPointer and input_list[leftPointer] < pivot:
                leftPointer += 1
            # 找到第一个小于或等于pivot的元素
            while leftPointer <= rightPointer and input_list[rightPointer] > pivot:
                rightPointer -= 1

            # 如果指针尚未交叉,则交换元素
            if leftPointer <= rightPointer:
                input_list[leftPointer], input_list[rightPointer] = input_list[rightPointer], input_list[leftPointer]
                # 交换后,移动指针继续寻找
                leftPointer += 1
                rightPointer -= 1

        # 4. 将支点放到其最终位置
        # 循环结束后,leftPointer指向第一个大于等于pivot的元素的位置
        # 将pivot(原位于high)与leftPointer指向的元素交换
        # 这样,pivot就位于所有小于它的元素之后,所有大于它的元素之前
        input_list[leftPointer], input_list[high] = input_list[high], input_list[leftPointer]

        # 5. 递归排序左右子数组
        # 支点现在位于leftPointer位置,所以递归范围是(low, leftPointer-1) 和 (leftPointer+1, high)
        self.quickSort(input_list, low, leftPointer - 1)
        self.quickSort(input_list, leftPointer + 1, high)

        return input_list

修正后的关键点解释:

  1. 支点选择与指针初始化:我们仍然选择 input_list[high] 作为支点。leftPointer 从 low 开始,rightPointer 从 high - 1 开始,这是因为 high 位置是支点,不需要参与初始的比较交换。
  2. 分区循环 (while leftPointer <= rightPointer)
    • 内部的 while 循环分别寻找左侧第一个大于等于支点的元素和右侧第一个小于等于支点的元素。
    • 当找到这样的两个元素且 leftPointer <= rightPointer 时,进行交换。
    • 交换后,leftPointer 和 rightPointer 都向前或向后移动一位,继续寻找。
  3. 支点最终放置:在主 while 循环结束后,leftPointer 会指向支点最终应该放置的位置(即所有小于支点的元素都在其左侧,所有大于支点的元素都在其右侧)。我们将原支点 (input_list[high]) 与 input_list[leftPointer] 进行交换,从而将支点放置到其最终的有序位置。
  4. 递归调用边界:由于支点已经放置在 leftPointer 位置,并且它已经处于最终的有序状态,因此在递归调用时,我们将数组分为 (low, leftPointer - 1) 和 (leftPointer + 1, high) 两个子数组,不包括支点本身。

示例代码与测试

为了验证修正后的快速排序算法的正确性,我们可以使用不同的测试用例:

# 实例化快速排序类
quick = QuickSort()

# 测试用例1:普通乱序数组
list1 = [50, 49, 19, 4, 9]
print(f"原始数组: {list1}, 排序后: {quick.quickSort(list1, 0, len(list1) - 1)}") # 预期: [4, 9, 19, 49, 50]

# 测试用例2:已排序数组
list2 = [1, 2, 3, 4, 5]
print(f"原始数组: {list2}, 排序后: {quick.quickSort(list2, 0, len(list2) - 1)}") # 预期: [1, 2, 3, 4, 5]

# 测试用例3:逆序数组
list3 = [4, 3, 2, 1]
print(f"原始数组: {list3}, 排序后: {quick.quickSort(list3, 0, len(list3) - 1)}") # 预期: [1, 2, 3, 4]

# 测试用例4:包含重复元素的数组
list4 = [8, 6, 7, 5, 3, 0, 9, 7, 1]
print(f"原始数组: {list4}, 排序后: {quick.quickSort(list4, 0, len(list4) - 1)}") # 预期: [0, 1, 3, 5, 6, 7, 7, 8, 9]

# 测试用例5:空数组或单元素数组
list5 = []
print(f"原始数组: {list5}, 排序后: {quick.quickSort(list5, 0, len(list5) - 1) if list5 else []}") # 预期: []

list6 = [42]
print(f"原始数组: {list6}, 排序后: {quick.quickSort(list6, 0, len(list6) - 1)}") # 预期: [42]

注意事项与总结

  1. 支点选择:本教程中选择最后一个元素作为支点。其他策略包括选择第一个元素、中间元素或随机选择。不同的支点选择策略对算法的性能有影响,尤其是在处理特定输入(如已排序或逆序数组)时。
  2. 性能:快速排序在平均情况下的时间复杂度为 O(n log n),但在最坏情况下(例如,每次都选择最大或最小元素作为支点,且数组已排序或逆序)会退化到 O(n^2)。随机化支点选择可以有效降低遇到最坏情况的概率。
  3. 空间复杂度:快速排序是一种原地排序算法,其空间复杂度主要取决于递归的深度,平均为 O(log n),最坏情况下为 O(n)。
  4. 稳定性:快速排序是一种不稳定的排序算法,即相等元素的相对顺序在排序后可能会改变。

通过理解和掌握正确的快速排序分区逻辑,开发者可以避免常见的实现错误,构建出高效且可靠的排序解决方案。核心在于确保支点在每次分区后都能准确地放置在其最终位置,并且递归调用能够正确地处理左右子数组。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

409

2023.09.04

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

106

2023.09.25

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

497

2023.08.14

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

69

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

37

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

82

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

97

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.9万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号