【十大排序算法】桶排序

news2024/12/24 0:21:09

在时间的琴弦上,桶排序如同一曲清澈的溪流,将数字的芬芳温柔地分拣,沉静地落入各自的花瓣般的容器中。

文章目录

  • 一、桶排序
  • 二、发展历史
  • 三、处理流程
  • 四、算法实现
  • 五、算法特性
  • 六、小结
  • 推荐阅读

一、桶排序

桶排序(Bucket sort)是一种排序算法,其工作原理是将数组分到有限数量的桶里。每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序),最后依次把各个桶中的记录列出来得到有序序列。

桶排序的核心在于合理设计桶的数量和每个桶的范围,使得数据能均匀分布到各个桶中,进而降低后续排序的复杂度。当待排序数据分布均匀且范围已知时,桶排序能充分利用数据特性,实现高效排序。

二、发展历史

桶排序是一种排序算法,其发展历史可以追溯到 1970 年代。以下是桶排序的发展历史:

  1. 早期思想: 桶排序最早可能出现在计算机科学的早期阶段,但并没有被正式提出。早期的计算机科学家可能会考虑将数据分组放入“桶”中,然后对每个桶中的数据进行排序。
  2. 1970 年代: 桶排序的概念可能最早出现在 1970 年代。在这个时期,人们开始思考如何改进传统的比较排序算法,以提高排序的效率。桶排序被提出作为一种可能的改进方法。
  3. 1980 年代: 在这个时期,桶排序算法开始被正式提出和研究。人们开始探讨如何实现桶排序以及如何优化它的性能。1980 年代是计算机科学发展的重要时期,许多经典的算法被提出和研究。
  4. 1990 年代: 随着计算机硬件的发展和算法研究的深入,桶排序算法得到了更广泛的应用和研究。人们开始研究如何在不同情况下使用桶排序,并探索如何优化算法以提高排序的效率。
  5. 2000 年代至今: 桶排序算法在这个时期得到了进一步的发展和改进。随着大数据时代的到来,人们开始思考如何将桶排序算法与并行计算、分布式计算等技术相结合,以应对更大规模的数据排序问题。

三、处理流程

场景假设:我们需要将下面的无序序列使用桶排序按从小到大进行排序。
workspace (15).png
桶排序的流程如下:

  1. 初始化桶:首先,我们需要确定桶的数量。在这个例子中,我们可以选择 10 个桶,每个桶代表一个范围,例如,第一个桶存储 0-9 之间的数,第二个桶存储 10-19 之间的数,以此类推。

workspace (17).png

  1. 分配元素到桶:然后,我们将每个元素放入对应的桶中。例如,29 会被放入第三个桶 [20-29],3 会被放入第一个桶(0-9),依此类推。

workspace (20).png

  1. 对每个桶进行排序:接下来,我们对每个桶中的元素进行排序。我们可以使用任何排序算法,例如插入排序、选择排序等。

workspace (21).png

  1. 合并桶:最后,我们按照桶的顺序,依次取出每个桶中的元素,合并成一个有序序列。

workspace (22).png

四、算法实现

public class BucketSort {
    public static void bucketSort(int[] arr) {
        // 检查数组是否为空或者长度为0
        if (arr == null || arr.length == 0) {
            return;
        }

        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        // 找出数组中的最大值和最小值
        for (int num : arr) {
            max = Math.max(max, num);
            min = Math.min(min, num);
        }

        // 计算桶的数量
        int bucketNum = (max - min) / arr.length + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
        for (int i = 0; i < bucketNum; i++) {
            bucketArr.add(new ArrayList<>());
        }

        // 将每个元素放入桶
        for (int i = 0; i < arr.length; i++) {
            int num = (arr[i] - min) / (arr.length);
            bucketArr.get(num).add(arr[i]);
        }

        // 对每个桶进行排序
        for (int i = 0; i < bucketArr.size(); i++) {
            Collections.sort(bucketArr.get(i));
        }

        // 将桶中的元素赋值到原序列
        int index = 0;
        for (ArrayList<Integer> arrayList : bucketArr) {
            for (Integer integer : arrayList) {
                arr[index++] = integer;
            }
        }
    }
}

算法时间复杂度分析:

情况时间复杂度计算公式公式解释
最好情况 O ( n + k ) O(n + k) O(n+k) T ( n ) = n + k T(n) = n + k T(n)=n+k当输入的数据可以均匀的分配到每一个桶中,每个桶中的数据量很小,可以看作是常数时间,所以此时的时间复杂度为 O ( n + k ) O(n + k) O(n+k)。这里的 n n n是待排序元素的数量, k k k是桶的数量。
平均情况 O ( n + k ) O(n + k) O(n+k) T ( n ) = n + k T(n) = n + k T(n)=n+k在平均情况下,每一个桶中的数据将近为 n / k n/k n/k,那么排序的时间复杂度近似于 O ( n + k ) O(n + k) O(n+k)。这里的 n n n是待排序元素的数量, k k k是桶的数量。
最坏情况 O ( n 2 ) O(n ^ 2) O(n2) T ( n ) = n 2 T(n) = n ^ 2 T(n)=n2当所有的数据都分配到一个桶中时,此时就退化为了基数排序,所以最坏时间复杂度为 O ( n 2 ) O(n ^ 2) O(n2)。这里的 n n n是待排序元素的数量。

五、算法特性

桶排序是一种分布式排序算法,其特性包括:

  1. 稳定性: 如果在桶内排序时使用的是稳定的排序算法(比如插入排序),并且在合并桶的过程中保持桶的顺序,则桶排序是稳定的。稳定性指的是相等元素的相对位置在排序前后不发生改变,桶排序在满足上述条件时能够保持相等元素的相对顺序。
  2. 原地性: 桶排序通常不是原地排序算法,因为它需要额外的空间来存储桶以及桶内的元素。桶排序的空间复杂度与输入数据的特性和桶的数量有关,通常情况下需要额外的线性空间。
  3. 适用场景: 桶排序适用于输入数据分布较均匀的情况,特别是适用于有着已知范围的整数排序。在这种情况下,可以根据范围划分桶,每个桶内的数据量相对较小,利于高效地进行排序。
  4. 分桶思想: 桶排序将待排序的元素分配到不同的桶中,每个桶内的元素具有一定的范围,通常是根据输入数据的特性和分布情况确定的。分桶的过程可以利用映射函数,将元素映射到对应的桶中。
  5. 桶内排序: 桶排序对每个桶内的元素进行排序,可以使用其他排序算法,如插入排序、快速排序等。桶内排序通常选择适合当前桶大小的高效排序算法。
  6. 桶间排序: 当所有的桶都排好序后,桶排序将按照桶的顺序依次合并起来,形成最终的有序序列。通常情况下,可以简单地按照桶的顺序将各个桶中的元素依次输出,从而形成有序序列。

六、小结

桶排序算法作为一种简单而高效的排序方法,在某些特定情况下展现出了其独特的优势。通过合理地选择桶的数量和映射函数,以及高效地处理桶内元素,桶排序可以在某些情况下达到接近线性时间复杂度的排序效果。然而,在应用桶排序时需要注意数据分布的情况,以及对额外空间的需求。

推荐阅读

  1. Spring 三级缓存
  2. 深入了解 MyBatis 插件:定制化你的持久层框架
  3. Zookeeper 注册中心:单机部署
  4. 【JavaScript】探索 JavaScript 中的解构赋值
  5. 深入理解 JavaScript 中的 Promise、async 和 await

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

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

相关文章

组长:你熟悉过React,开发个Next项目模板吧,我:怎么扯上关系的?

最近工作安排我开发一个Next.js项目模板&#xff0c;心里默笑&#xff0c;React用得少得都快忘光了&#xff0c;现在得搞Next&#xff1f;虽然我曾是React的老用户&#xff0c;但转投Vue阵营已久&#xff0c;React的点点滴滴早已一干二净。 不过&#xff0c;挑战归挑战&#x…

【ARM】MDK如何进入\退出debug模式时断点不会消失

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 在对于工程进行调试的情况下&#xff0c;退出debug模式后再次进入&#xff0c;之前设置的断点不会消失。 2、 问题场景 在对于工程进行调试的时候&#xff0c;通常是通过设置断点的方式对于语句进行检测&#xff0…

【启明智显实战指南】SSD202D方案双网口开发板烧录全攻略---从入门到精通

提示&#xff1a;作为Espressif&#xff08;乐鑫科技&#xff09;大中华区合作伙伴及sigmastar&#xff08;厦门星宸&#xff09;VAD合作伙伴&#xff0c;我们不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程供开发小伙伴参考。同时也用心整理了乐鑫及星宸…

游戏试玩站打码zq平台系统可运营的任务网源码

安装说明 1.恢复数据&#xff1b; 2.数据连接库配置路径&#xff1a;protected\config\mail.php 文件中修改第60行 &#xff08;记得不要用记事本修改&#xff0c;否则可能会出现验证码显示不了问题&#xff0c;建议用Notepad&#xff09; 3.浏览器访问输入 127.0.0.2 显示界…

哈尔滨等保测评内容科普

#网络安全等级保护 #哈尔滨等保测评 1. 等保测评的概念 等保测评的全称为“信息安全等级保护测评”。它通过对各个层次的信息系统提供安全保障&#xff0c;从而保证了信息的安全与保密性。 2. 哈尔滨等保测评的意义 随着我国信息化进程的不断推进&#xff0c;网络的信息安…

【学习笔记】C++每日一记[20240612]

给定两个有序的数组&#xff0c;计算两者的交集 给定两个有序整型数组&#xff0c;数组中 的元素是递增的&#xff0c;且各数组中没有重复元素。 第一时间解法&#xff1a;通过一个循环扫描array_1中的每一个元素&#xff0c;然后利用该元素去比较array_2中的每一个元素&…

说说你对Rust的了解?

Rust 是一种系统编程语言&#xff0c;由Mozilla开发&#xff0c;于2010年首次发布。它旨在提供与C和C等低级语言相媲美的性能&#xff0c;同时通过其独特的内存安全保证来避免诸如缓冲区溢出等常见安全问题。Rust的设计哲学融合了现代编程语言的特性&#xff0c;包括内存安全、…

精密结构件核心供应商「东创集团」×企企通启动SRM采购数字化项目,共同驱动供应链价值跃升

导读 此次采购数字化项目上线可有效打通东创集团业务全面信息化的最后一公里&#xff0c;为公司柔性交付提供系统助力。在项目建设阶段&#xff0c;希望各业务关键人员从业务需求出发&#xff0c;设计好蓝图去打通堵点、断点&#xff0c;各相关部门要高度配合&#xff0c;组织…

Java从放弃到继续放弃

并发编程 为什么需要多线程&#xff1f; 由于硬件的发展&#xff0c;CPU的核数增多&#xff0c;如果仍然使用单线程对CPU资源会造成浪费。同时&#xff0c;单线程也会出现阻塞的问题。所以&#xff0c;选择向多线程转变。 多线程的使用使得程序能够并行计算&#xff0c;提高计…

MT2092 水温调节

代码&#xff1a; #include <bits/stdc.h> using namespace std; double t1, t2, x1, x2, t0; double y1, y2, t; double tmax 0x3f3f3f3f, ans1, ans2; int main() {cin >> t1 >> t2 >> x1 >> x2 >> t0;y1 x1, y2 x2; // 初始流速赋最…

提升易用性,OceanBase生态管控产品的“从小到大”

2022年&#xff0c;OceanBase发布4.0版本“小鱼”&#xff0c;并首次公开提出了单机分布式一体化这一理念&#xff0c;旨在适应大小不同规模的工作负载&#xff0c;全面满足用户数据库“从小到大”全生命周期的需求。当时&#xff0c;我们所说的“从小到大”主要聚焦于数据库的…

Stable Diffusion 如何写出更优雅的 Prompt

在看了前面的课程后&#xff0c; 相信很多人都会有一个困惑&#xff0c;这个 prompt 咋写… 为什么我写的时候只能憋出来了一个 a girl, a boy, beautify … 再也想不到其他的了&#xff0c; 总感觉是吃了没文化的亏&#xff1f; 这一节课我们就来讲一讲 如何写好 prompt …

JVM (四)GC过程

一。概述 程序计数器、虚拟机栈、本地方法栈都是随线程生灭&#xff0c;栈帧随着方法的进入和退出做入栈和出栈操作&#xff0c;实现了自动的内存清理&#xff0c;因此&#xff0c;内存垃圾回收主要集中于Java堆和方法区中。 GC整体流程示意图&#xff1a; ① 年轻代对象的移动…

【UE5|水文章】在UMG上显示帧率

参考视频&#xff1a; https://www.youtube.com/watch?vH_NdvImlI68 蓝图&#xff1a;

解决生产问题的万能接口(Java编译器API的使用)

文章目录 前言Tool和ToolProvider编译器工具&#xff1a;JavaCompiler文件管理文件&#xff1a;FileObject文件管理器&#xff1a;JavaFileManager 诊断监听器&#xff1a;DiagnosticDemo&#xff1a;allPowerfulInterface具体实现测试 结语 前言 当生产环境出现问题时&#x…

【大模型应用开发极简入门】提示工程一:1. 通过context、task、role文本结构设计有效的提示词、 2. OpenAI的提示词任务示例

文章目录 一. chat_completion函数二. 设计有效的提示词1.上下文1.1. 更多细节的上下文1.2. 让GPT改进上下文 2.任务2.1. 提供足够的任务信息2.2. OpenAI的任务示例语法纠正总结TL;DR概要Python转自然语言计算时间复杂度修复Python bug产生python函数 3.角色 了解LLM和OpenAI A…

【Linux】基础IO [万字之作]

目录 一.重谈文件 二.重谈C文件操作 1.操作 1.文件的打开和关闭 2.文件的读写操作 ​编辑 1.fgetc函数 2.fputc函数 3.fputs函数 4.fgets函数 5.fprintf函数 6.fscanf函数 7.fread函数 8.fwrite函数 三.重谈当前路径 四.系统文件操作接口 1.Open函数 2.write函数 3…

假期抢票难?程序员手写一个超强抢票脚本,轻松购得出行票!

距离五一假期只剩几天的时间&#xff0c;据央视财经报道&#xff0c;从4月17日开始&#xff0c;5月1日的火车票就可以通过铁路12306网站核车站售票窗口购买了&#xff0c;售票通道一打开&#xff0c;5月1日上午的热门目的地车票&#xff0c;几乎瞬间售罄。 有平台预计&#xff…

conda虚拟环境,安装pytorch cuda cudnn版本一致,最简单方式

1、pytorch版本安装&#xff08;卸载也会有问题&#xff09; &#xff08;1&#xff09;版本如何选择参考和卸载 https://zhuanlan.zhihu.com/p/401931724 &#xff08;2&#xff09;对应版本如何安装命令 https://pytorch.org/get-started/previous-versions/ 最简答安装参考…

网络数据包抓取与分析工具wireshark的安及使用

WireShark安装和使用 WireShark是非常流行的网络封包分析工具&#xff0c;可以截取各种网络数据包&#xff0c;并显示数据包详细信息。常用于开发测试过程中各种问题定位。 1 任务目标 1.1 知识目标 了解WireShark的过滤器使用,通过过滤器可以筛选出想要分析的内容 掌握Wir…