【Python】九大经典排序算法:从入门到精通的详解(冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序、计数排序、基数排序、桶排序)

news/2024/11/27 3:41:26/

文章目录

    • 1. 冒泡排序(Bubble Sort)
    • 2. 选择排序(Selection Sort)
    • 3. 插入排序(Insertion Sort)
    • 4. 归并排序(Merge Sort)
    • 5. 快速排序(Quick Sort)
    • 6. 堆排序(Heap Sort)
    • 7. 计数排序(Counting Sort)
    • 8. 基数排序(Radix Sort)
    • 9. 桶排序(Bucket Sort)
    • 10. 更多实用文章
    • 11. 结语

在这里插入图片描述

算法>排序算法对比表格

算法>排序算法时间复杂度空间复杂度稳定性适用场景
冒泡排序O(n²)O(1)稳定小规模数据或几乎有序的数据
选择排序O(n²)O(1)不稳定数据量小且对稳定性无要求
插入排序O(n²)O(1)稳定小规模数据或几乎有序的数据
归并排序O(n log n)O(n)稳定大规模数据需要稳定性的场景
快速排序O(n log n)O(log n)不稳定大规模数据,平均情况高效
堆排序O(n log n)O(1)不稳定大规模数据,不需要稳定性
计数排序O(n + k)O(k)稳定整数且范围有限的数据
基数排序O(d*(n + k))O(n + k)稳定大规模整数或可以分位处理的数据
桶排序O(n + k)O(n)稳定均匀分布的大规模数据

1. 冒泡排序(Bubble Sort)

工作原理

冒泡排序是一种简单的交换算法>排序算法,通过重复遍历要排序的列表,比较相邻元素并交换顺序错误的元素,直到整个列表有序。每一次遍历都会将未排序部分的最大元素“冒泡”到列表末尾。
在这里插入图片描述

实现步骤

  1. 从列表的起始位置开始,比较相邻的两个元素。
  2. 如果前一个元素比后一个元素大,则交换它们的位置。
  3. 对整个列表重复上述过程,每完成一轮遍历,未排序部分的元素数量减少一位。
  4. 当一轮遍历未发生任何交换时,意味着列表已经有序,可以提前终止算法

Python 实现

python">def bubble_sort(arr):n = len(arr)for i in range(n):swapped = Falsefor j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]swapped = Trueif not swapped:breakreturn arr

优点

  • 实现简单,理解容易。
  • 对于少量数据或已经基本有序的数据,效率较高。

缺点:

  • 时间复杂度高,为 O(n²)。
  • 不适合大规模数据排序。

2. 选择排序(Selection Sort)

工作原理

选择排序是一种简单直观的算法>排序算法。它通过多次从未排序部分选择最小(或最大)的元素,放到已排序部分的末尾,逐步完成排序过程。
在这里插入图片描述

实现步骤

  1. 从未排序部分中找到最小的元素。
  2. 将该最小元素与未排序部分的第一个元素交换位置。
  3. 缩小未排序部分的范围,重复上述过程,直到所有元素都有序。

Python 实现

python">def selection_sort(arr):n = len(arr)for i in range(n):min_idx = ifor j in range(i+1, n):if arr[j] < arr[min_idx]:min_idx = jarr[i], arr[min_idx] = arr[min_idx], arr[i]return arr

优点:

  • 实现简单,无需额外的内存空间。
  • 适用于数据量较小的情况。

缺点:

  • 时间复杂度为 O(n²),效率较低。
  • 不稳定排序,可能破坏相同元素的相对顺序。

3. 插入排序(Insertion Sort)

工作原理

插入排序通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。类似于扑克牌的排序方式。
在这里插入图片描述

实现步骤

  1. 从第二个元素开始,假设第一个元素为已排序部分。
  2. 取未排序部分的第一个元素,将其插入到已排序部分的适当位置。
  3. 重复上述过程,直到整个列表有序。

Python 实现

python">def insertion_sort(arr):for i in range(1, len(arr)):key = arr[i]j = i-1while j >=0 and key < arr[j]:arr[j+1] = arr[j]j -= 1arr[j+1] = keyreturn arr

优点:

  • 实现简单,效率较高,对于少量数据或基本有序的数据效果不错。
  • 稳定排序,保持相同元素的相对位置。

缺点:

  • 最坏情况下时间复杂度为 O(n²)。
  • 对于大规模数据排序效率低下。

4. 归并排序(Merge Sort)

工作原理

归并排序采用分治法,将数组分成两半,分别进行排序后再合并。其核心在于有效地将两个有序数组合并成一个有序数组。

体验最新GPT系列模型、支持自定义助手、文件上传等功能:ChatMoss & ChatGPT-AI中文版
在这里插入图片描述

实现步骤

  1. 如果数组长度小于等于1,直接返回。
  2. 将数组分成两半,分别对左右两部分进行归并排序。
  3. 合并两部分,生成有序的数组。

Python 实现

python">def merge_sort(arr):if len(arr) <=1:return arrmid = len(arr)//2left = merge_sort(arr[:mid])right = merge_sort(arr[mid:])return merge(left, right)def merge(left, right):merged = []i=j=0while i<len(left) and j<len(right):if left[i] < right[j]:merged.append(left[i])i+=1else:merged.append(right[j])j+=1merged.extend(left[i:])merged.extend(right[j:])return merged

优点:

  • 时间复杂度稳定为 O(n log n)。
  • 稳定排序,保持相同元素的相对位置。
  • 适用于大规模数据。

缺点:

  • 需要额外的内存空间,空间复杂度为 O(n)。

5. 快速排序(Quick Sort)

工作原理

快速排序同样采用分治策略,通过选择一个“基准”元素,将数组分成两部分,一部分小于基准元素,另一部分大于基准元素,然后递归排序两部分。
在这里插入图片描述

实现步骤

  1. 选择数组中的一个元素作为基准(通常选择第一个元素)。
  2. 重新排列数组,将小于基准的元素放到左边,大于基准的元素放到右边。
  3. 递归对左右两部分进行快速排序。

Python 实现

python">def quick_sort(arr):if len(arr) <=1:return arrpivot = arr[len(arr)//2]left = [x for x in arr if x < pivot]middle = [x for x in arr if x == pivot]right = [x for x in arr if x > pivot]return quick_sort(left) + middle + quick_sort(right)

优点:

  • 平均时间复杂度为 O(n log n),表现优异。
  • 不需要额外的内存空间(原地排序实现时)。
  • 通常比其他 O(n log n) 算法更快,尤其在实践中表现良好。

缺点:

  • 最坏情况下时间复杂度为 O(n²),如已排序数据。
  • 不稳定排序,可能破坏相同元素的相对位置。

6. 堆排序(Heap Sort)

工作原理

堆排序利用堆这种数据结构,首先将数组构建成一个最大堆(或最小堆),然后依次将堆顶元素(最大或最小)移到数组末尾,调整堆,重复此过程直到整个数组有序。
在这里插入图片描述

实现步骤

  1. 将数组构建成一个最大堆。
  2. 将堆顶元素与数组末尾元素交换,缩小堆的范围。
  3. 对堆顶进行堆调整,保持堆性质。
  4. 重复步骤2和3,直到堆的范围为1。

Python 实现

python">def heapify(arr, n, i):largest = il = 2*i +1r = 2*i +2if l < n and arr[l] > arr[largest]:largest = lif r < n and arr[r] > arr[largest]:largest = rif largest !=i:arr[i], arr[largest] = arr[largest], arr[i]heapify(arr, n, largest)def heap_sort(arr):n = len(arr)for i in range(n//2 -1, -1, -1):heapify(arr, n, i)for i in range(n-1, 0, -1):arr[i], arr[0] = arr[0], arr[i]heapify(arr, i, 0)return arr

优点:

  • 时间复杂度为 O(n log n)。
  • 不需要额外的内存空间(原地排序)。
  • 对于大规模数据表现稳定。

缺点:

  • 通常比快速排序慢,常数因子较大。
  • 不稳定排序,可能破坏相同元素的相对位置。

7. 计数排序(Counting Sort)

工作原理

计数排序是一种稳定的线性时间算法>排序算法,适用于元素范围较小的整数排序。它通过统计每个元素出现的次数,计算元素的位置,最后构建有序数组。

体验最新GPT系列模型、支持自定义助手、文件上传等功能:ChatMoss & ChatGPT-AI中文版
在这里插入图片描述

实现步骤

  1. 找到待排序数组的最大值和最小值。
  2. 创建一个计数数组,统计每个元素的出现次数。
  3. 计算计数数组的前缀和,确定每个元素在有序数组中的位置。
  4. 构建有序数组,确保稳定性。

Python 实现

python">def counting_sort(arr):if not arr:return arrmax_val = max(arr)min_val = min(arr)range_of_elements = max_val - min_val +1count = [0]*range_of_elementsfor num in arr:count[num - min_val] +=1for i in range(1, len(count)):count[i] += count[i-1]output = [0]*len(arr)for num in reversed(arr):output[count[num - min_val] -1] = numcount[num - min_val] -=1return output

优点:

  • 时间复杂度为 O(n + k),其中 k 是元素的范围。
  • 稳定排序,保持相同元素的相对顺序。

缺点:

  • 只能用于整数排序,且元素范围较小。
  • 需要额外的内存空间,尤其当元素范围较大时。

8. 基数排序(Radix Sort)

工作原理

基数排序是一种非比较型算法>排序算法,通过将元素按位(如个位、十位等)进行多次排序,实现整体有序。常结合计数排序作为子过程。
在这里插入图片描述

实现步骤

  1. 确定元素的最大位数。
  2. 从最低位开始,对所有元素进行稳定排序(如使用计数排序)。
  3. 重复上述过程,直到所有位数排序完成。

Python 实现

python">def counting_sort_for_radix(arr, exp):n = len(arr)output = [0]*ncount = [0]*10for num in arr:index = num//expcount[index %10] +=1for i in range(1,10):count[i] += count[i-1]for num in reversed(arr):index = num//expoutput[count[index %10] -1] = numcount[index %10] -=1return outputdef radix_sort(arr):if not arr:return arrmax_val = max(arr)exp =1while max_val//exp >0:arr = counting_sort_for_radix(arr, exp)exp *=10return arr

优点:

  • 时间复杂度为 O(d*(n + k)),d 是位数,k 是基数。
  • 稳定排序,保持相同元素的相对顺序。
  • 适用于大规模数据和大位数整数排序。

缺点:

  • 只能用于整数排序,或可以拆分为位进行排序的对象。
  • 需要额外的内存空间,尤其是基数较大时。

9. 桶排序(Bucket Sort)

工作原理

桶排序将元素分到多个桶中,每个桶内部再采用其他算法>排序算法排序,最后将所有桶中的元素按顺序合并。适用于元素均匀分布的情况。
在这里插入图片描述

实现步骤

  1. 确定桶的数量和范围。
  2. 将每个元素分配到对应的桶中。
  3. 对每个桶内部进行排序(如使用插入排序)。
  4. 按顺序合并所有桶中的元素,得到有序数组。

Python 实现

python">def bucket_sort(arr):if not arr:return arrbucket_count = 10min_val = min(arr)max_val = max(arr)range_val = (max_val - min_val)/bucket_countbuckets = [[] for _ in range(bucket_count)]for num in arr:index = int((num - min_val)/range_val)if index == bucket_count:index -=1buckets[index].append(num)for bucket in buckets:insertion_sort(bucket)sorted_arr = []for bucket in buckets:sorted_arr.extend(bucket)return sorted_arr

10. 更多实用文章

【IDER、PyCharm】免费AI编程工具完整教程:ChatGPT Free - Support Key call AI GPT-o1 Claude3.5

【VScode】VSCode中的智能编程利器,全面揭秘ChatMoss & ChatGPT中文版

【OpenAI】获取OpenAI API Key的多种方式全攻略:从入门到精通,再到详解教程!!

11. 结语

通过这篇详尽的算法>排序算法教程,希望能帮助你在编程学习和实际项目中游刃有余地应用各种排序技术,提升整体编程技能与算法素养。


http://www.ppmy.cn/news/1550228.html

相关文章

PyTorch2

Tensor的常见操作&#xff1a; 获取元素值&#xff1a; 注意&#xff1a; 和Tensor的维度没有关系&#xff0c;都可以取出来&#xff01; 如果有多个元素则报错&#xff1b; import torch def test002():data torch.tensor([18])print(data.item())pass if __name__ &qu…

【高阶数据结构】图论

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是图&#xff0c;并能掌握深度优先遍历和广度优先遍历。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持…

单片机结合OpenCV

目录 一、引言 二、单片机结合 OpenCV 的优势 1. 图像识别与处理 2. 目标检测 3. 用户界面开发 4. Linux 在嵌入式系统中的作用 5. 多线程优势 6. 网络编程作用 7. 文件编程功能 三、OpenCV 在单片机上的实现难点 1. 处理能力限制 2. 通信与优化挑战 四、单片机如…

《基于FPGA的便携式PWM方波信号发生器》论文分析(二)——方波信号产生

一、论文概述 基于FPGA的便携式PWM方波信号发生器是一篇由任青颖、庹忠曜、黄洵桢、李智禺和张贤宇 等人发表的一篇期刊论文。该论文主要研究了一种新型的信号发生器&#xff0c;旨在解决传统PWM信号发生器在移动设备信号调控中存在的精准度低和便携性差的问题 。其基于现场可编…

xtu oj Estrella‘s Chocolate

样例输入 2 5 2 5 3 2 4 1 5 3 5 3 2 4 1样例输出 8 5 解题思路&#xff1a;二分法&#xff0c;emm……&#xff0c;感觉挺难想到的。 问题简化 给定一个数组&#xff0c;和一个值k&#xff0c;数组分成k段。要求这k段子段和最大值最小。求出这个值。 1、求出数组中的最大…

裸金属服务器能够帮助企业解决哪些问题?

随着网络科技的快速发展&#xff0c;企业业务也在不断的进行扩张和复杂化&#xff0c;传统的服务已经无法满足企业对于高性能和高稳定性的需求&#xff0c;而裸金属服务器则能够帮助企业来解决这一问题&#xff0c;下面我们就来具体看一下吧&#xff01; 裸金属服务器能够允许应…

组合模式和适配器模式的区别

组合模式&#xff08;Composite Pattern&#xff09;和适配器模式&#xff08;Adapter Pattern&#xff09;都是结构型设计模式&#xff0c;它们解决的问题不同&#xff0c;应用场景也不一样。下面我来对比一下这两种模式的区别&#xff1a; 1. 目标和用途 组合模式&#xff0…

力扣—53. 最大子数组和

53. 最大子数组和 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4…