Python 新手入门,第一个排序算法怎么写
为什么从冒泡排序开始很多刚接触 Python 的朋友一听到“算法”两个字就觉得头大仿佛要面对什么高深的数学公式或者复杂的逻辑迷宫。其实算法的本质就是解决问题的步骤。就像你整理书架上的书总得有个顺序是按作者名字排还是按书名高低排这个“整理的过程”就是算法。在众多的排序算法中冒泡排序Bubble Sort虽然在实际工程中效率不是最高的但它绝对是新手入门的“最佳陪练”。它的逻辑非常直观几乎不需要额外的数据结构知识只需要理解最基础的循环和条件判断就能掌握。更重要的是它能完美地展示计算机是如何通过“比较”和“交换”来让数据变得有序的。今天我们就抛开那些枯燥的理论定义直接动手用 Python 写出你的第一个排序算法。算法核心逻辑像气泡一样浮上来想象一下你有一杯刚倒好的汽水里面有很多小气泡。这些气泡大小不一代表了我们数组里乱序的数字。冒泡排序的名字由来就是因为最大的那个数字或者说最重的元素会像水里的大气泡一样经过不断的比较和交换慢慢地“浮”到数列的最顶端也就是数组的末尾。这个过程具体是怎么发生的呢我们可以把它拆解成两个关键动作相邻比较从头开始拿着第一个数和第二个数比。如果前面的数比后面的大那就把它们俩的位置互换如果前面的已经比后面小了那就保持不动。重复推进接着拿第二个数和第三个数比重复上面的动作。一直比到这一轮的最后一个数。当你把这一整套动作从头到尾做了一遍后你会发现整个数组里最大的那个数一定已经被挪到了最后面。这就好比第一轮比赛结束冠军已经诞生了并且站到了领奖台的最右侧。接下来我们只需要对剩下的那些还没排好序的数重复同样的过程。第二轮结束后第二大的数就会停在倒数第二的位置。如此循环往复直到所有的数都各就各位。这里有一个非常关键的概念也是新手最容易晕的地方双重循环。外层循环控制我们要进行多少轮“冒泡”。如果有 N 个数理论上我们需要 N-1 轮就能排完因为最后一个数自然就位了。内层循环负责在每一轮里执行具体的“相邻比较”和“交换”动作。随着轮数增加后面已经排好的数就不需要再参与了所以内层循环的范围会逐渐缩小。代码实战逐行拆解与注释光说不练假把式。下面这段代码就是完整的冒泡排序实现。我会像带着你写代码一样把每一行的意图都讲清楚。你可以直接把这段代码复制到你的 Python 编辑器里运行。def bubble_sort(arr): # 获取列表的长度也就是我们要处理的元素个数 n len(arr) # 外层循环控制排序的轮数 # 范围是 0 到 n-1意味着我们最多需要进行 n-1 轮比较 for i in range(n): # 标记变量用于优化算法 # 假设这一轮开始时列表已经是有序的了 swapped False # 内层循环负责每一轮的具体比较工作 # 注意这里的范围n - 1 - i # 为什么要减 i因为每一轮结束后末尾的 i 个元素已经是最大的且有序的了不需要再比较 for j in range(0, n - 1 - i): # 核心逻辑比较相邻的两个元素 # 如果前一个元素 (arr[j]) 大于后一个元素 (arr[j1]) if arr[j] arr[j 1]: # 交换位置 # Python 特有的语法糖不需要临时变量就能直接交换 arr[j], arr[j 1] arr[j 1], arr[j] # 既然发生了交换说明列表之前并不是有序的 swapped True # 优化检查如果在这一轮完整的内层循环中一次交换都没有发生 # 说明列表已经完全有序了我们可以提前结束不用再跑剩下的轮数 if not swapped: break # 测试数据一个乱序的整数列表 numbers [64, 34, 25, 12, 22, 11, 90] print(排序前的列表:, numbers) bubble_sort(numbers) print(排序后的列表:, numbers)重点细节解析在这段代码中有几个地方值得你停下来仔细琢磨首先是range(0, n - 1 - i)这个写法。很多初学者会直接写成range(n)这虽然也能跑通但效率很低。试想一下第一轮结束后最大的数已经在最后了第二轮再比较到最后一个是毫无意义的因为它肯定比前面的大。减去i就是为了避免这种无效劳动让内层循环的范围随着外层轮数的增加而动态缩小。其次是swapped标志位的使用。这是一个很好的编程习惯。假如你传入的列表本来就是[1, 2, 3, 4, 5]如果没有这个优化程序还是会傻傻地跑完所有外层循环做大量无用的比较。有了它程序在内层循环发现一次交换都没发生时就会立刻break跳出极大地提升了在“基本有序”情况下的性能。最后是 Python 的交换语法a, b b, a。在其他语言如 C 或 Java 中你可能需要定义一个temp临时变量来暂存数据才能交换但在 Python 里这一行代码就优雅地解决了问题既简洁又易读。运行结果与可视化观察当你运行上面的代码时控制台会输出以下内容排序前的列表[64, 34, 25, 12, 22, 11, 90] 排序后的列表[11, 12, 22, 25, 34, 64, 90]为了让你更清楚地看到“冒泡”的过程我们可以稍微修改一下代码在每次交换时打印出当前的状态实际开发中当然不会这么做但这对于学习非常有用# 仅用于演示过程的简化版片段 arr [5, 1, 4, 2, 8] n len(arr) for i in range(n): for j in range(0, n - 1 - i): if arr[j] arr[j 1]: arr[j], arr[j 1] arr[j 1], arr[j] print(f交换了 {arr[j1]} 和 {arr[j]} - 当前列表{arr})运行这段演示代码你会看到数字8是如何一步步从中间位置经过多次交换最终“浮”到最右边的。紧接着是5然后是4……这种动态的变化过程能帮你建立起对算法执行流的直观感受。你会发现越往后的轮次需要移动的距离越短因为后面的“大块头”都已经就位了。新手常见错误排查在自己动手尝试时你可能会遇到一些典型的“坑”提前了解这些能帮你节省不少调试时间。1. 索引越界错误IndexError这是最常见的报错。通常发生在内层循环的范围设置上。如果你写成了range(n - i)那么当j取到最大值时j 1就会等于n而列表的最大索引是n - 1。访问arr[n]自然会报错。解决方法务必记住内层循环的上限是n - 1 - i确保j 1永远不会超出列表边界。2. 缩进混乱导致逻辑失效Python 对缩进非常敏感。如果把if not swapped: break这句话缩进错了层级比如缩进了内层循环里那么只要有一次没交换循环就会立即终止导致排序只进行了一半。解决方法检查break语句是否与内层的for循环对齐它应该是在内层循环完全结束后才执行的判断。3. 混淆了“原地排序”与“返回值”上面的bubble_sort函数没有return任何值因为它直接修改了传入的列表原地排序。有些新手会在调用后写new_list bubble_sort(numbers)然后打印new_list结果发现是None。解决方法理解 Python 列表的可变性。直接打印原列表numbers即可看到排序结果或者在函数末尾显式加上return arr。4. 比较方向搞反如果你想实现从大到小排序却仍然使用if arr[j] arr[j 1]那结果依然是从小到大。解决方法想要降序排列只需将大于号改为小于号逻辑就变成了“如果前面的比后面的小就交换”这样小的数就会慢慢浮上去大的数沉下来。动手练习建议看懂了不代表学会了。建议你关掉代码尝试自己在空白文件里重新写一遍冒泡排序。可以先从一个只有 5 个数字的列表开始手动模拟一遍交换过程然后再敲代码验证。试着修改一下代码让它支持用户输入任意一组数字进行排序或者挑战一下统计一下你的算法到底进行了多少次比较和交换。这些小小的变式练习能帮你把“双重循环”的逻辑彻底刻在脑子里。当你能够不假思索地写出这个结构时恭喜你你已经正式迈过了算法入门的第一道门槛接下来的归并排序、快速排序等更高级的算法也不过是在此基础上的演变而已。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2566026.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!