算法02-各种排序算法

各种常见排序算法总结

一. 冒泡排序 (Bubble Sort)

冒泡排序是一种简单的排序算法。它重复地遍历要排序的列表,比较相邻的元素,并交换它们的位置,直到整个列表排序完成。

A、说明:

特点:
  • 通过不断交换相邻元素,将最大(或最小)的元素“冒泡”到数组的一端。
优点:
  • 实现简单,代码容易理解。
  • 对于小规模数据表现较好。
缺点:
  • 时间复杂度较高,不适合大规模数据。
  • 交换操作较多,效率低。
时间复杂度:
  • 最好情况:O(n)(已经有序)
  • 最坏情况:O(n²)
  • 平均情况:O(n²)
空间复杂度:
  • O(1)(原地排序)
稳定性:
  • 稳定

B、步骤:

  1. 从列表的第一个元素开始,比较相邻的两个元素。

  2. 如果前一个元素比后一个元素大,交换它们的位置。

  3. 继续遍历列表,直到没有需要交换的元素。

C、示例代码

def bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]return arr# 示例
arr = [64, 34, 25, 12, 22, 11, 90]
print("排序前:", arr)
print("排序后:", bubble_sort(arr))

二、选择排序 (Selection Sort)

选择排序是一种简单直观的排序算法。它的工作原理是每次从未排序的部分中选择最小(或最大)的元素,放到已排序部分的末尾。

A、说明:

特点:
  • 每次从未排序部分选择最小(或最大)的元素,放到已排序部分的末尾。
优点:
  • 实现简单。
  • 不占用额外空间。
缺点:
  • 时间复杂度较高,不适合大规模数据。
  • 不稳定(可能改变相同元素的相对顺序)。
时间复杂度:
  • 最好情况:O(n²)
  • 最坏情况:O(n²)
  • 平均情况:O(n²)
空间复杂度:
  • O(1)(原地排序)
稳定性:
  • 不稳定

B、步骤:

  1. 在未排序部分中找到最小元素。

  2. 将最小元素与未排序部分的第一个元素交换。

  3. 重复上述步骤,直到所有元素排序完成。

C、示例代码

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# 示例
arr = [64, 25, 12, 22, 11]
print("排序前:", arr)
print("排序后:", selection_sort(arr))

三、插入排序 (Insertion Sort)

插入排序是一种简单直观的排序算法。它的工作原理是将未排序部分的元素逐个插入到已排序部分的适当位置。

A、说明:

特点:
  • 将未排序部分的元素逐个插入到已排序部分的正确位置。
优点:
  • 对于小规模或基本有序的数据效率较高。
  • 实现简单。
缺点:
  • 时间复杂度较高,不适合大规模数据。
  • 数据移动较多。
时间复杂度:
  • 最好情况:O(n)(已经有序)
  • 最坏情况:O(n²)
  • 平均情况:O(n²)
空间复杂度:
  • O(1)(原地排序)
稳定性:
  • 稳定

B、步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序。

  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描。

  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置。

  4. 重复步骤3,直到找到已排序的元素小于或等于新元素的位置。

  5. 将新元素插入到该位置后。

  6. 重复步骤2~5。

C、示例代码:

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# 示例
arr = [12, 11, 13, 5, 6]
print("排序前:", arr)
print("排序后:", insertion_sort(arr))

四、快速排序 (Quick Sort)

快速排序是一种高效的排序算法,采用分治法策略。它通过选择一个“基准”元素,将数组分为两部分,一部分比基准小,另一部分比基准大,然后递归地对这两部分进行排序。

A、说明:

特点:
  • 采用分治法,选择一个基准元素,将数组分为两部分,左边小于基准,右边大于基准,然后递归排序。
优点:
  • 平均情况下效率非常高。
  • 适合大规模数据。
缺点:
  • 最坏情况下时间复杂度较高(O(n²))。
  • 不稳定。
时间复杂度:
  • 最好情况:O(n log n)
  • 最坏情况:O(n²)(当数组已经有序时)
  • 平均情况:O(n log n)
空间复杂度:
  • O(log n)(递归栈空间)
稳定性:
  • 不稳定

B、步骤:

  1. 选择一个基准元素。

  2. 将数组分为两部分:一部分比基准小,另一部分比基准大。

  3. 递归地对这两部分进行快速排序。

C、示例代码:

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)# 示例
arr = [10, 7, 8, 9, 1, 5]
print("排序前:", arr)
print("排序后:", quick_sort(arr))

五、归并排序 (Merge Sort)

归并排序是一种稳定的排序算法,采用分治法策略。它将数组分成两半,分别对它们进行排序,然后将排序后的两半合并。

A、说明:

特点:
  • 采用分治法,将数组分成两部分,分别排序后合并。
优点:
  • 时间复杂度稳定,适合大规模数据。
  • 稳定排序。
缺点:
  • 需要额外的存储空间。
  • 对于小规模数据效率不如插入排序。
时间复杂度:
  • 最好情况:O(n log n)
  • 最坏情况:O(n log n)
  • 平均情况:O(n log n)
空间复杂度:
  • O(n)(需要额外的数组空间)
稳定性:
  • 稳定

B、步骤:

  1. 将数组分成两半。

  2. 递归地对每一半进行归并排序。

  3. 将排序后的两半合并。

C、示例代码:

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):result = []i = j = 0while i < len(left) and j < len(right):if left[i] < right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result.extend(left[i:])result.extend(right[j:])return result# 示例
arr = [38, 27, 43, 3, 9, 82, 10]
print("排序前:", arr)
print("排序后:", merge_sort(arr))

六、堆排序 (Heap Sort)

堆排序是一种基于二叉堆的排序算法。它首先将数组构建成一个最大堆,然后逐步将堆顶元素(最大值)与堆的最后一个元素交换,并调整堆,直到整个数组排序完成。

A、说明:

特点:
  • 利用堆数据结构,将数组构建成最大堆(或最小堆),然后逐个取出堆顶元素。
优点:
  • 时间复杂度稳定,适合大规模数据。
  • 不占用额外空间(原地排序)。
缺点:
  • 不稳定。
  • 实现较复杂。
时间复杂度:
  • 最好情况:O(n log n)
  • 最坏情况:O(n log n)
  • 平均情况:O(n log n)
空间复杂度:
  • O(1)(原地排序)
稳定性:
  • 不稳定

B、步骤:

  1. 构建一个最大堆。

  2. 将堆顶元素(最大值)与堆的最后一个元素交换。

  3. 调整堆,使其重新成为最大堆。

  4. 重复步骤2~3,直到堆的大小为1。

C、示例代码:

def heapify(arr, n, i):largest = ileft = 2 * i + 1right = 2 * i + 2if left < n and arr[i] < arr[left]:largest = leftif right < n and arr[largest] < arr[right]:largest = rightif 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# 示例
arr = [12, 11, 13, 5, 6, 7]
print("排序前:", arr)
print("排序后:", heap_sort(arr))

七、希尔排序 (Shell Sort)

希尔排序是插入排序的一种高效改进版本。它通过将数组分成若干个子序列,分别进行插入排序,然后逐步缩小子序列的间隔,最终完成排序。

A、说明:

特点:
  • 是插入排序的改进版,通过分组插入排序,逐步缩小分组间隔。
优点:
  • 对于中等规模数据效率较高。
  • 比插入排序更快。
缺点:
  • 时间复杂度依赖于增量序列的选择。
  • 不稳定。
时间复杂度:
  • 最好情况:O(n log n)
  • 最坏情况:O(n²)
  • 平均情况:取决于增量序列
空间复杂度:
  • O(1)(原地排序)
稳定性:
  • 不稳定

B、步骤:

  1. 选择一个增量序列(例如,n/2, n/4, …, 1)。

  2. 对每个增量进行插入排序。

  3. 逐步缩小增量,直到增量为1。

C、示例代码:

def shell_sort(arr):n = len(arr)gap = n // 2while gap > 0:for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempgap //= 2return arr# 示例
arr = [12, 34, 54, 2, 3]
print("排序前:", arr)
print("排序后:", shell_sort(arr))

八、计数排序 (Counting Sort)

计数排序是一种非比较排序算法,适用于整数排序。它通过统计每个元素的出现次数,然后根据统计结果将元素放回正确的位置。

A、说明:

特点:
  • 适用于整数排序,通过统计每个元素的出现次数,然后依次输出。
优点:
  • 时间复杂度低,适合数据范围较小的整数排序。
缺点:
  • 需要额外的存储空间。
  • 只适用于整数排序。
时间复杂度:
  • 最好情况:O(n + k)(k是数据范围)
  • 最坏情况:O(n + k)
  • 平均情况:O(n + k)
空间复杂度:
  • O(k)(需要额外的计数数组)
稳定性:
  • 稳定

B、步骤:

  1. 统计每个元素的出现次数。

  2. 计算每个元素在排序后数组中的位置。

  3. 将元素放回正确的位置。

C、示例代码:

def counting_sort(arr):max_val = max(arr)count = [0] * (max_val + 1)for num in arr:count[num] += 1sorted_arr = []for i in range(len(count)):sorted_arr.extend([i] * count[i])return sorted_arr# 示例
arr = [4, 2, 2, 8, 3, 3, 1]
print("排序前:", arr)
print("排序后:", counting_sort(arr))

九、桶排序 (Bucket Sort)

桶排序是一种分布式排序算法,它将元素分到若干个桶中,每个桶分别进行排序,最后将桶中的元素合并。

A、说明:

特点:
  • 将数据分到多个桶中,每个桶单独排序,最后合并。
优点:
  • 适合数据分布均匀的情况。
  • 时间复杂度较低。
缺点:
  • 需要额外的存储空间。
  • 数据分布不均匀时效率下降。
时间复杂度:
  • 最好情况:O(n + k)(k是桶的数量)
  • 最坏情况:O(n²)
  • 平均情况:O(n + k)
空间复杂度:
  • O(n + k)(需要额外的桶空间)
稳定性:
  • 稳定

B、步骤:

  1. 将元素分到若干个桶中。

  2. 对每个桶中的元素进行排序。

  3. 将桶中的元素合并。

C、示例代码:

def bucket_sort(arr):max_val = max(arr)min_val = min(arr)bucket_range = (max_val - min_val) / len(arr)buckets = [[] for _ in range(len(arr))]for num in arr:index = int((num - min_val) // bucket_range)if index != len(arr):buckets[index].append(num)else:buckets[-1].append(num)sorted_arr = []for bucket in buckets:sorted_arr.extend(sorted(bucket))return sorted_arr# 示例
arr = [0.42, 0.32, 0.33, 0.52, 0.37, 0.47, 0.51]
print("排序前:", arr)
print("排序后:", bucket_sort(arr))

十、基数排序 (Radix Sort)

基数排序是一种非比较排序算法,它通过将整数按位数切割成不同的数字,然后按每个位数分别进行排序。

A、说明:

特点:
  • 按照位数从低到高(或从高到低)依次排序。
优点:
  • 适合整数或字符串排序。
  • 时间复杂度较低。
缺点:
  • 需要额外的存储空间。
  • 只适用于整数或字符串排序。
时间复杂度:
  • 最好情况:O(n × k)(k是最大位数)
  • 最坏情况:O(n × k)
  • 平均情况:O(n × k)
空间复杂度:
  • O(n + k)(需要额外的桶空间)
稳定性:
  • 稳定

B、步骤:

  1. 找到数组中的最大数,确定最大位数。

  2. 从最低位开始,对数组进行计数排序。

  3. 重复步骤2,直到最高位。

C、示例代码:

def counting_sort_for_radix(arr, exp):n = len(arr)output = [0] * ncount = [0] * 10for i in range(n):index = arr[i] // expcount[index % 10] += 1for i in range(1, 10):count[i] += count[i - 1]i = n - 1while i >= 0:index = arr[i] // expoutput[count[index % 10] - 1] = arr[i]count[index % 10] -= 1i -= 1for i in range(n):arr[i] = output[i]def radix_sort(arr):max_val = max(arr)exp = 1while max_val // exp > 0:counting_sort_for_radix(arr, exp)exp *= 10return arr# 示例
arr = [170, 45, 75, 90, 802, 24, 2, 66]
print("排序前:", arr)
print("排序后:", radix_sort(arr))

十一、总结对比:

排序算法最好时间复杂度最坏时间复杂度平均时间复杂度空间复杂度稳定性优点缺点适用场景
冒泡排序(O(n))(O(n^2))(O(n^2))(O(1))稳定实现简单,适合小规模数据效率低,不适合大规模数据小规模数据
选择排序(O(n^2))(O(n^2))(O(n^2))(O(1))不稳定实现简单,不占用额外空间效率低,不适合大规模数据小规模数据
插入排序(O(n))(O(n^2))(O(n^2))(O(1))稳定对小规模数据或基本有序数据效率高效率低,不适合大规模数据小规模或基本有序数据
快速排序(O(n \log n))(O(n^2))(O(n \log n))(O(\log n))不稳定平均情况下效率高,适合大规模数据最坏情况下效率低(如数据已经有序)大规模数据
归并排序(O(n \log n))(O(n \log n))(O(n \log n))(O(n))稳定时间复杂度稳定,适合大规模数据需要额外空间,对小规模数据效率不如插入排序大规模数据
堆排序(O(n \log n))(O(n \log n))(O(n \log n))(O(1))不稳定时间复杂度稳定,适合大规模数据实现较复杂,不稳定大规模数据
希尔排序(O(n \log n))(O(n^2))(O(n \log n))(O(1))不稳定对小规模数据效率较高,比插入排序更快时间复杂度依赖于增量序列的选择中等规模数据
计数排序(O(n + k))(O(n + k))(O(n + k))(O(n + k))稳定时间复杂度低,适合数据范围较小的整数排序需要额外空间,仅适用于整数数据范围较小的整数排序
桶排序(O(n + k))(O(n^2))(O(n + k))(O(n + k))稳定适合数据分布均匀的情况需要额外空间,对数据分布不均匀的情况效率低数据分布均匀的情况
基数排序(O(n \times k))(O(n \times k))(O(n \times k))(O(n + k))稳定适合整数排序,尤其是位数较少的情况需要额外空间,仅适用于整数整数或字符串排序

© 著作权归作者所有

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/70846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型数据集全面整理:444个数据集下载地址

本文针对Datasets for Large Language Models: A Comprehensive Survey 中的 444 个数据集&#xff08;涵盖8种语言类别和32个领域&#xff09;进行完整下载地址整理收集。 2024-02-28&#xff0c;由杨刘、曹家欢、刘崇宇、丁凯、金连文等作者编写&#xff0c;深入探讨了大型语…

2025届优秀大数据毕业设计

【2025计算机毕业设计】计算机毕业设计100个高通过率选题推荐&#xff0c;毕业生毕设必看选题指导&#xff0c;计算机毕业设计选题讲解&#xff0c;毕业设计选题详细指导_哔哩哔哩_bilibili 985华南理工大学学长 大厂全栈&#xff0c;大数据开发工程师 专注定制化开发

免费在腾讯云Cloud Studio部署DeepSeek-R1大模型

2024年2月2日&#xff0c;腾讯云宣布DeepSeek-R1大模型正式支持一键部署至腾讯云HAI&#xff08;高性能应用服务&#xff09;。开发者仅需3分钟即可完成部署并调用模型&#xff0c;大幅简化了传统部署流程中买卡、装驱动、配网络、配存储、装环境、装框架、下载模型等繁琐步骤。…

【C++高并发服务器WebServer】-17:阻塞/非阻塞和同步/异步、五种IO模型、Web服务器

本文目录 一、阻塞/非阻塞、同步/异步1.1 辨析1.2 异步io接口 二、五种IO模型2.1 阻塞 blocking 模型2.2 非阻塞 NIO 模型2.3 IO多路复用2.4 信号驱动Signal-driven2.5 异步 三、Web Sever 网页服务器3.1 HTTP的请求响应步骤3.2 HTTP请求与响应报文格式3.3 HTTP请求方法3.4 HTT…

【MySQL例题】我在广州学Mysql 系列——有关数据备份与还原的示例

ℹ️大家好&#xff0c;我是练小杰&#xff0c;今天周二&#xff0c;明天就是元宵节了呀&#xff01;&#xff01;&#x1f606; 俗话说“众里寻他千百度。蓦然回首&#xff0c;那人却在&#xff0c;灯火阑珊处。” 本文主要对数据库备份与还原的知识点例题学习~~ 前情回顾&…

自动化xpath定位元素(附几款浏览器xpath插件)

在 Web 自动化测试、数据采集、前端调试中&#xff0c;XPath 仍然是不可或缺的技能。虽然 CSS 选择器越来越强大&#xff0c;但面对复杂 DOM 结构时&#xff0c;XPath 仍然更具灵活性。因此&#xff0c;掌握 XPath&#xff0c;不仅能提高自动化测试的稳定性&#xff0c;还能在爬…

【并发控制、更新、版本控制】.NET开源ORM框架 SqlSugar 系列

系列文章目录 &#x1f380;&#x1f380;&#x1f380; .NET开源 ORM 框架 SqlSugar 系列 &#x1f380;&#x1f380;&#x1f380; 文章目录 系列文章目录一、并发累计&#xff08;累加&#xff09;1.1 单条批量累计1.2 批量更新并且字段11.3 批量更新并且字段list中对应的…

数据存储和操作:数据管理的基石

在数据管理的庞大体系中&#xff0c;数据存储和操作是确保数据可用性和完整性的关键环节。它不仅涉及数据的物理存储&#xff0c;还包括数据的管理、维护和优化。今天&#xff0c;让我们深入《DAMA数据管理知识体系指南&#xff08;第二版&#xff09;》的第六章&#xff0c;一…

Redis 数据类型 Hash 哈希

在 Redis 中&#xff0c;哈希类型是指值本⾝⼜是⼀个键值对结构&#xff0c;形如 key "key"&#xff0c;value { { field1, value1 }, ..., {fieldN, valueN } }&#xff0c;Redis String 和 Hash 类型⼆者的关系可以⽤下图来表⽰。 Hash 数据类型的特点 键值对集合…

支持向量机原理

支持向量机&#xff08;简称SVM&#xff09;虽然诞生只有短短的二十多年&#xff0c;但是自一诞生便由于它良好的分类性能席卷了机器学习领域。如果不考虑集成学习的算法&#xff0c;不考虑特定的训练数据集&#xff0c;尤其在分类任务中表现突出。在分类算法中的表现SVM说是排…

zy.21

PHP(续) PHP代码执行漏洞 1.PHP中代码漏洞的概念 代码执行漏洞就是在代码中若存在eval、assert等能将所接收的参数作为代码去执行,并且拼接的内容可被访问者控制,也就是把传入的参数给拼接进去了,造成了额外的代码执行,也就造成了代码执行漏洞。&#xff08;大概原理&#x…

LSTM 学习笔记 之pytorch调包每个参数的解释

0、 LSTM 原理 整理优秀的文章 LSTM入门例子&#xff1a;根据前9年的数据预测后3年的客流&#xff08;PyTorch实现&#xff09; [干货]深入浅出LSTM及其Python代码实现 整理视频 李毅宏手撕LSTM [双语字幕]吴恩达深度学习deeplearning.ai 1 Pytorch 代码 这里直接调用了nn.l…

React - 事件绑定this

在 React 中&#xff0c;this 的绑定是一个常见问题&#xff0c;尤其在类组件中使用事件处理函数时。JavaScript 中的 bind 函数用于设置函数调用时 this 的值。 bind 函数的作用 bind() 方法创建一个新的函数&#xff0c;当被调用时&#xff0c;其 this 关键字被设置为提供的…

Web3 的虚实融合之路:从虚拟交互到元宇宙构建

在这个数字技术日新月异的时代&#xff0c;我们正站在 Web3 的门槛上&#xff0c;见证着互联网的又一次革命。Web3 不仅仅是技术的迭代&#xff0c;它代表了一种全新的交互方式和价值创造模式。本文将探讨 Web3 如何推动虚拟交互的发展&#xff0c;并最终实现元宇宙的构建&…

Kafka简单使用

说明&#xff1a;kafka是一款消息中间件&#xff0c;可实现微服务之间的异步调用。本文介绍kafka的简单使用。windows操作系统下的kafka安装&#xff0c;参考下面这篇文章 Kafka安装 启动 按照上面博客的介绍&#xff0c;使用CMD命令启动&#xff0c;如下&#xff1a; Demo …

【原创精品】基于Springboot3+Vue3的学习计划管理系统

大家好&#xff0c;我是武哥&#xff0c;最近给大家手撸了一个基于SpringBoot3Vue3的学习计划管理系统&#xff0c;可用于毕业设计、课程设计、练手学习&#xff0c;系统全部原创&#xff0c;如有遇到网上抄袭站长的&#xff0c;欢迎联系博主~ 项目演示视频 https://www.bili…

C++引用深度详解

C引用深度详解 前言1. 引用的本质与核心特性1.1 引用概念1.2 核心特性 2. 常引用与权限控制2.1 权限传递规则2.2 常量引用2.3 临时变量保护1. 样例2. 样例3. 测试 三、引用使用场景分析3.1 函数参数传递输出型参数避免多级指针高效传参 3.2 做函数返回值正确使用危险案例 4. 性…

本地部署Deepseek R1

使用Ollama open-webui部署Deepseek R1 一、安装Ollama 官网地址&#xff1a;https://ollama.com/&#xff0c;点击下载按钮选择windows版本。并安装 打开命令提示符输入ollama&#xff0c;出现一下提示命令表示ollama安装完成 二、使用Ollama下载deepseek R1不同模型 打开o…

MATLAB 生成脉冲序列 pulstran函数使用详解

MATLAB 生成脉冲序列 pulstran函数使用详解 目录 前言 一、参数说明 二、示例一 三、示例二 总结 前言 MATLAB中的pulstran函数用于生成脉冲序列&#xff0c;支持连续或离散脉冲。该函数通过将原型脉冲延迟并相加&#xff0c;生成脉冲序列&#xff0c;适用于信号处理和系统…

机器学习(李宏毅)——self-Attention

一、前言 本文章作为学习2023年《李宏毅机器学习课程》的笔记&#xff0c;感谢台湾大学李宏毅教授的课程&#xff0c;respect&#xff01;&#xff01;&#xff01; 二、大纲 何为self-Attention&#xff1f;原理剖析self-Attention VS CNN、RNN、GNN 三、何为self-Attenti…