【算法基础】一文掌握十大排序算法,冒泡排序、插入排序、选择排序、归并排序、计数排序、基数排序、希尔排序和堆排序

news2024/12/23 10:02:47

目录

1 冒泡排序(Bubble Sort)

2 插入排序(Insertion Sort)

3 选择排序(Selection Sort)

4. 快速排序(Quick Sort)

5. 归并排序(Merge Sort)

6 堆排序 (Heap Sort)

7 计数排序 (Counting Sort)

8 基数排序 (Radix Sort)

9 希尔排序(Shell Sort)

10 桶排序


   

1 冒泡排序(Bubble Sort)

       冒泡排序是一种基本的排序算法,其核心思想是多次遍历待排序的元素,比较相邻的两个元素,如果它们的顺序不正确,则交换它们,直到整个数组按照指定顺序排列。

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]

# 示例用法
arr = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(arr)
print("冒泡排序后的数组:", arr)

        冒泡排序通过多次遍历数组,每次比较相邻的两个元素,如果它们的顺序不正确就交换它们。这个过程将最大的元素逐渐“冒泡”到数组的末尾。

        

        时间复杂度为 O(n^2),不适合大规模数据集。 

2 插入排序(Insertion Sort)

        插入排序是一种稳定的排序算法,其核心思想是将未排序的元素逐个插入到已排序的部分,从前往后遍历,保持前面的元素有序。

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            # 将较大的元素向右移动
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key

# 示例用法
arr = [64, 34, 25, 12, 22, 11, 90]
insertion_sort(arr)
print("插入排序后的数组:", arr)

        插入排序逐个将未排序的元素插入到已排序的部分,从前往后遍历,保持前面的元素有序。时间复杂度为 O(n^2),适合小规模数据集和部分有序的数据。 

3 选择排序(Selection Sort)

        选择排序是一种简单的不稳定排序算法,其核心思想是找到未排序部分的最小元素,将其与未排序部分的第一个元素交换位置。

def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_index = i
        for j in range(i+1, n):
            # 找到未排序部分的最小元素的索引
            if arr[j] < arr[min_index]:
                min_index = j
        # 交换最小元素与未排序部分的第一个元素
        arr[i], arr[min_index] = arr[min_index], arr[i]

# 示例用法
arr = [64, 34, 25, 12, 22, 11, 90]
selection_sort(arr)
print("选择排序后的数组:", arr)

      选择排序通过多次选择未排序部分的最小元素,并将其与未排序部分的第一个元素交换位置来进行排序。时间复杂度为 O(n^2),不适合大规模数据集。

4. 快速排序(Quick Sort)

        快速排序是一种高效的分治排序算法,它选择一个基准元素,将数组分成两部分,左边的元素都小于基准,右边的元素都大于基准,然后递归对左右两部分进行排序。

def quick_sort(arr):
    # 基本情况:如果数组为空或只包含一个元素,无需排序
    if len(arr) <= 1:
        return arr
    
    # 选择中间元素作为基准点(pivot)
    pivot = 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 = [64, 34, 25, 12, 22, 11, 90]
arr = quick_sort(arr)
print("快速排序后的数组:", arr)
  • 快速排序是一种高效的分治排序算法,它通过选择一个基准点(通常是数组中的中间元素)将数组分成左右两部分,并递归地对左右两部分进行排序。
  • 基本情况是数组为空或只包含一个元素,无需排序。
  • 针对每个元素,将它与基准点进行比较,分成小于、等于和大于基准点的三个子数组。
  • 然后,递归地对左右两部分进行排序,最后将它们与基准点合并,形成一个有序的数组。

5. 归并排序(Merge Sort)

        归并排序是一种稳定的分治排序算法,它将数组分成两半,分别排序,然后将已排序的两个子数组合并成一个有序数组。

def merge_sort(arr):
    # 基本情况:如果数组为空或只包含一个元素,无需排序
    if len(arr) <= 1:
        return arr
    
    # 将数组分成两半
    mid = len(arr) // 2
    left = arr[:mid]
    right = arr[mid:]
    
    # 递归地对左右两部分进行排序
    left = merge_sort(left)
    right = merge_sort(right)
    
    # 合并已排序的左右两部分
    return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0
    
    # 合并两个已排序的子数组
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    
    # 如果左边或右边的子数组还有剩余元素,将它们添加到结果中
    result.extend(left[i:])
    result.extend(right[j:])
    
    return result

# 示例用法
arr = [64, 34, 25, 12, 22, 11, 90]
arr = merge_sort(arr)
print("归并排序后的数组:", arr)
  • 归并排序是一种稳定的分治排序算法,它将数组递归分成两半,然后合并已排序的子数组。
  • 基本情况是数组为空或只包含一个元素,无需排序。
  • 递归地对左右两部分进行排序,然后使用 merge 函数将它们合并成一个有序的数组。
  • merge 函数将两个已排序的子数组合并,同时维护它们的有序性。

6 堆排序 (Heap Sort)

        堆排序是一种不稳定的排序算法,它使用堆数据结构(通常是最大堆)来进行排序。堆排序分为两个主要步骤:建立堆和排序。

def heapify(arr, n, i):
    largest = i
    left = 2 * i + 1
    right = 2 * i + 2

    # 找到左子节点和右子节点中的最大值
    if left < n and arr[left] > arr[largest]:
        largest = left

    if right < n and arr[right] > arr[largest]:
        largest = right

    # 如果最大值不是当前节点,交换它们
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]

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)

# 示例用法
arr = [64, 34, 25, 12, 22, 11, 90]
heap_sort(arr)
print("堆排序后的数组:", arr)
  • 排序使用堆数据结构(通常是最大堆)来进行排序。首先构建最大堆,然后一个接一个地从堆中取出元素,交换根节点与最后一个节点,然后重新构建堆。
  • heapify 函数用于维护堆的性质,即父节点的值大于或等于子节点的值。
  • 这个算法的时间复杂度为 O(nlogn),是一种高效的排序算法。

7 计数排序 (Counting Sort)

        计数排序是一种非比较排序算法,它根据输入元素的计数来对元素进行排序。它适用于整数或有限范围内的非负整数。

def counting_sort(arr):
    max_val = max(arr)
    min_val = min(arr)
    range_of_elements = max_val - min_val + 1
    count_arr = [0] * range_of_elements
    output_arr = [0] * len(arr)

    # 计数每个元素的出现次数
    for num in arr:
        count_arr[num - min_val] += 1

    # 计算每个元素的累积计数
    for i in range(1, len(count_arr)):
        count_arr[i] += count_arr[i - 1]

    # 根据累积计数将元素放入输出数组
    for i in range(len(arr) - 1, -1, -1):
        output_arr[count_arr[arr[i] - min_val] - 1] = arr[i]
        count_arr[arr[i] - min_val] -= 1

    return output_arr

# 示例用法
arr = [4, 2, 2, 8, 3, 3, 1]
arr = counting_sort(arr)
print("计数排序后的数组:", arr)
  • 计数排序是一种非比较排序算法,适用于整数或有限范围内的非负整数。
  • 首先,计算每个元素的出现次数,然后计算每个元素的累积计数,最后根据累积计数将元素放入输出数组。
  • 这个算法的时间复杂度为 O(n+k),其中 k 是输入范围的大小。 

8 基数排序 (Radix Sort)

        基数排序是一种非比较排序算法,它将数字按照每个位数进行排序,从最低位到最高位,依次排列。

def counting_sort(arr, exp):
    n = len(arr)
    output = [0] * n
    count = [0] * 10

    # 计数每个元素的出现次数
    for i in range(n):
        index = arr[i] // exp
        count[index % 10] += 1

    # 计算每个元素的累积计数
    for i in range(1, 10):
        count[i] += count[i - 1]

    # 根据累积计数将元素放入输出数组
    i = n - 1
    while i >= 0:
        index = arr[i] // exp
        output[count[index % 10] - 1] = arr[i]
        count[index % 10] -= 1
        i -= 1

    # 将输出数组的内容复制到原始数组中
    for i in range(n):
        arr[i] = output[i]

def radix_sort(arr):
    max_val = max(arr)
    exp = 1
    while max_val // exp > 0:
        counting_sort(arr, exp)
        exp *= 10

# 示例用法
arr = [170, 45, 75, 90, 802, 24, 2, 66]
radix_sort(arr)
print("基数排序后的数组:", arr)
  • 基数排序是一种非比较排序算法,它按照每个位数进行排序,从最低位到最高位,依次排列。
  • 首先使用计数排序对每个位数进行排序,然后再次对下一个位数进行排序,依次进行直到最高位。
  • 这个算法的时间复杂度为 O(nk),其中 k 是数字的最大位数。

9 希尔排序(Shell Sort)

        希尔排序(Shell Sort)是一种插入排序的改进版本,也被称为缩小增量排序。希尔排序通过将数组分成若干个子序列来排序数据,然后逐渐缩小子序列的间隔,最终得到一个完全排序的数组。希尔排序的主要思想是提前交换较远的元素,以加快排序过程。

算法原理

  1. 选择一个增量序列(间隔序列),通常选择的增量是数组长度的一半,然后逐渐减小增量。

  2. 对于每个增量,将数组分成若干个子序列,每个子序列使用插入排序进行排序。

  3. 重复步骤2,逐渐减小增量,直到增量为1。

  4. 当增量为1时,整个数组成为一个序列,使用插入排序对其进行排序。

def shell_sort(arr):
    n = len(arr)
    gap = n // 2  # 初始增量取数组长度的一半

    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            # 使用插入排序对子序列进行排序
            while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        gap //= 2  # 缩小增量

# 示例用法
arr = [64, 34, 25, 12, 22, 11, 90]
shell_sort(arr)
print("希尔排序后的数组:", arr)

         希尔排序的关键在于选择合适的增量序列。常见的增量序列有希尔增量、Hibbard增量、Knuth增量等,不同的增量序列会影响排序的性能。

  • 希尔排序的时间复杂度取决于增量序列的选择,平均时间复杂度通常在 O(n^1.25) 到 O(n^2) 之间,比插入排序要快。

  • 希尔排序是一种不稳定排序算法,适用于中等大小的数据集。虽然不如快速排序和归并排序快,但在某些情况下比插入排序更快。希尔排序通常用于嵌入式系统等资源有限的环境。

10 桶排序(Bucket Sort)

         桶排序(Bucket Sort)是一种分布式排序算法,它将元素分散到一组桶中,然后对每个桶中的元素进行排序,最后将所有桶中的元素按顺序合并成一个有序序列。桶排序适用于元素均匀分布在一个范围内的情况,特别适用于浮点数排序。

算法原理

  1. 确定桶的数量和范围,通常根据输入数据的分布来选择桶的数量。如果元素均匀分布在一个范围内,那么可以选择桶的数量等于元素的数量。

  2. 将每个元素分配到相应的桶中。元素的分配可以采用不同的方法,例如线性划分或哈希函数。

  3. 对每个桶中的元素进行排序,可以使用任何排序算法,通常选择插入排序。

  4. 合并所有桶中的元素,按照桶的顺序得到最终的有序序列。

def bucket_sort(arr):
    # 确定桶的数量,这里选择与输入元素数量相同
    n = len(arr)
    if n <= 1:
        return arr

    # 初始化桶
    max_val = max(arr)
    min_val = min(arr)
    bucket_range = (max_val - min_val) / n  # 每个桶的范围
    bucket_count = n  # 桶的数量等于元素数量
    buckets = [[] for _ in range(bucket_count)]

    # 将元素分配到桶中
    for num in arr:
        index = int((num - min_val) / bucket_range)
        buckets[index].append(num)

    # 对每个桶中的元素进行排序
    for i in range(bucket_count):
        buckets[i].sort()

    # 合并所有桶中的元素
    sorted_arr = []
    for bucket in buckets:
        sorted_arr.extend(bucket)

    return sorted_arr

# 示例用法
arr = [0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434]
arr = bucket_sort(arr)
print("桶排序后的数组:", arr)

         桶排序的性能取决于桶的数量和元素的分布。如果元素均匀分布在一个范围内,并且桶的数量足够多,那么桶排序可以非常高效。

  • 桶排序的时间复杂度通常为 O(n + k),其中 n 是元素的数量,k 是桶的数量。

  • 桶排序是一种稳定排序算法,适用于浮点数排序等特定情况。不过,它需要额外的内存空间来存储桶,因此不适用于数据集非常大的情况。

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

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

相关文章

力扣 -- 44. 通配符匹配

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:bool isMatch(string s, string p) {int ms.size();int np.size();//为了调整映射关系s s;p p;//多开一行多开一列vector<vector<bool>> dp(m1,vector<bool>(n1,false));//初始化//dp[0]…

uniapp 实现下拉筛选框 二次开发定制

前言 最近又收到了一个需求&#xff0c;需要在uniapp 小程序上做一个下拉筛选框&#xff0c;然后找了一下插件市场&#xff0c;确实有找到&#xff0c;但不过他不支持搜索&#xff0c;于是乎&#xff0c;我就自动动手&#xff0c;进行了二开定制&#xff0c;站在巨人的肩膀上&…

asp.net core mvc 文件上传,下载,预览

//文件上传用到了IformFile接口 1.1文件上传视图 <form action"/stu/upload" method"post" enctype"multipart/form-data"><input type"file" name"img" /><input type"submit" value"上传&…

分类预测 | Matlab实现BES-ELM秃鹰搜索算法优化极限学习机分类预测

分类预测 | Matlab实现BES-ELM秃鹰搜索算法优化极限学习机分类预测 目录 分类预测 | Matlab实现BES-ELM秃鹰搜索算法优化极限学习机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 Matlab实现BES-ELM秃鹰搜索算法优化极限学习机分类预测&#xff08;完整源码和数…

深度学习算法在工业视觉落地的思考

0.废话 距离上次的栈板识别的思考已经过去3个月&#xff0c;中间根据客户的需求和自己的思考&#xff0c;对软件又重新做了调整。但是整体上还是不满意。 0.1 老生常谈的工业视觉落地架构 对于软件架构&#xff0c;我实在没有太多的参考。没办法&#xff0c;公司根本不关心软…

react+IntersectionObserver实现页面丝滑帧动画

实现效果&#xff1a; 加入帧动画前&#xff1a; 普通的静态页面 加入帧动画后&#xff1a; 可以看到&#xff0c;加入帧动画后&#xff0c;页面效果还是比较丝滑的。 技术实现 加入animation动画类 先用 **scss **定义三种动画类&#xff1a; .withAnimation {.fade1 {ani…

学会这些,QtIFW制作安装包不再是难题

一文看懂如何利用QtIFW制作安装包&#xff0c;小白也能看懂且学会的软件安装包制作教程&#xff1b;&#xff08;本文不基于Qt工程&#xff09; 1 前言 1.1 安装包制作工具的选择 安装程序生成工具就是将应用程序和依赖的文件打包到一个可执行的安装程序种&#xff0c;可以简…

HTML之如何下载网页中的音频(二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【算法】莫队

这篇博客起源于本人把一道 p o w ( 2 , n ) pow(2,n) pow(2,n) 的问题考虑成求组合数前缀和的问题qwq&#xff0c;于是接触到了这个新算法来总结一下 参考自这篇文章&#xff0c;写得太好了 首先是一道模板题 题目意思是&#xff0c;给出一个数组a&#xff0c;再给出多个区…

What is an HTTP Flood DDoS attack?

HTTP 洪水攻击是一种针对 Web 和应用程序服务器的第 7 层分布式拒绝服务 &#xff08;DDoS&#xff09; 攻击。HTTP 洪水攻击通过使用 HTTP GET 或 HTTP POST 请求执行 DDoS 攻击。这些请求是有效的&#xff0c;并且针对可用资源&#xff0c;因此很难防范 HTTP 洪水攻击。 匿名…

特斯拉——使用人工智能制造智能汽车

特斯拉(Tesla)是电动汽车开发和推广的先驱。特斯拉对自动驾驶汽车的未来寄予厚望--实际上&#xff0c;每一辆特斯拉汽车都有可能通过软件升级成为自动驾驶汽车。该公司还生产和销售高级电池和太阳能电池板。 汽车的自动驾驶是按从1~5的等级划分的。自适应巡航控制和自动停车系…

论文笔记(整理):轨迹相似度顶会论文中使用的数据集

0 汇总 数据类型数据名称数据处理出租车数据波尔图 原始数据&#xff1a;2013年7月到2014年6月&#xff0c;170万条数据 ICDE 2023 Contrastive Trajectory Similarity Learning with Dual-Feature Attention 过滤位于城市&#xff08;或国家&#xff09;区域之外的轨迹 过…

【SSL】用Certbot生成免费HTTPS证书

1. 实验背景 服务器&#xff1a;CentOS7.x 示例域名&#xff1a; www.example.com 域名对应的web站点目录&#xff1a; /usr/local/openresty/nginx/html 2. 安装docker # yum -y install yum-utils# yum-config-manager --add-repo https://download.docker.com/linux/ce…

采集SEO方法-优化内链与外链建设

采集大量的文章数据&#xff0c;要想批量做SEO优化添加内链外链方法&#xff0c;可以使用简数采集器的处理规则实现。 简数采集器的一个处理规则&#xff0c;可以包含多种SEO方法&#xff0c;还可自由组合&#xff0c;强大灵活方便。 优化内链外链的SEO技巧&#xff1a; 1&a…

基于PYQT5的GUI开发系列教程【二】QT五个布局的介绍与运用

目录 本文概述 作者介绍 创建主窗口 水平布局 垂直布局 栅格布局 分裂器水平布局 分裂器垂直布局 自由布局 取消原先控件的布局的方法 尾言 本文概述 PYQT5是一个基于python的可视化GUI开发框架&#xff0c;具有容易上手&#xff0c;界面美观&#xff0c;多平台…

基于SpringBoot的教学资源库系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 社会的进步&#xff0c;教育行业发展迅速&#xff0c;人们对教育越来越重视&#xff0c;在当今网络普及的情况下&#xff0c;教学模式也开始逐渐网络化&#xff0c;各大…

Python大数据之Python进阶(四)进程的注意点

文章目录 进程的注意点1. 进程的注意点介绍2. 进程之间不共享全局变量3. 进程之间不共享全局变量的小结4. 主进程会等待所有的子进程执行结束再结束5. 主进程会等待所有的子进程执行结束再结束的小结 进程的注意点 学习目标 能够说出进程的注意点 1. 进程的注意点介绍 进程之…

Polygon Miden交易模型:Actor模式 + ZKP => 并行 + 隐私

1. 引言 前序博客&#xff1a; Polygon Miden&#xff1a;扩展以太坊功能集的ZK-optimized rollupPolygon Miden zkRollup中的UTXO账户混合状态模型 Polygon Miden为&#xff1a; ZK-optimized rollup由客户端生成证明完善Polygon ZK系列解决方案&#xff0c;致力于成为网络…

nodejs+vue网上婚纱购物系统elementui

便了用户足不出门也能进行购物的理念&#xff0c;方便了婚纱影楼的对商品的进一步管理,互联网成为人们快速获取、发布、和传递信息的重要渠道&#xff0c;它在人们政治、经济、生活等各个方面发挥着重要的作用。未来的时代是网络信息的时代&#xff0c;“网上生活方式”是人类今…

软件测试面试复盘

作者&#xff1a;爱塔居 专栏&#xff1a;测试 1、计算机网络七层协议&#xff1a;物理层、数据链路层、网络层、传输层、表示层、会话层、应用层&#xff08;面试问过这个&#xff09; 2.TCP/IP四层模型&#xff1a;应用层、传输层、网络层、网络接口层&#xff08;笔试问过&…