Java实现十大经典排序算法详解


本文全面讲解十大经典排序算法的实现原理,并提供完整的Java代码实现。每种算法的时间复杂度、空间复杂度和稳定性分析见文末总结表格。


一、冒泡排序(Bubble Sort)

算法逻辑

  1. 依次比较相邻元素,前大后小则交换
  2. 每轮遍历将最大值冒泡到末尾
  3. 重复n-1轮完成排序
public static void bubbleSort(int[] arr) {for(int i=0; i<arr.length-1; i++) {for(int j=0; j<arr.length-1-i; j++) {if(arr[j] > arr[j+1]) {int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}
}

二、选择排序(Selection Sort)

算法逻辑

  1. 在未排序序列中找到最小元素
  2. 与序列起始位置元素交换
  3. 重复上述过程直到排序完成
public static void selectionSort(int[] arr) {for(int i=0; i<arr.length-1; i++) {int minIndex = i;for(int j=i+1; j<arr.length; j++) {if(arr[j] < arr[minIndex]) {minIndex = j;}}int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}
}

三、插入排序(Insertion Sort)

算法逻辑

  1. 将第一个元素视为已排序序列
  2. 取出下一个元素,在已排序序列中从后向前扫描
  3. 找到相应位置插入元素
  4. 重复步骤2-3
public static void insertionSort(int[] arr) {for(int i=1; i<arr.length; i++) {int current = arr[i];int j = i-1;while(j >=0 && arr[j] > current) {arr[j+1] = arr[j];j--;}arr[j+1] = current;}
}

四、希尔排序(Shell Sort)

算法逻辑

  1. 定义增量序列(本文使用gap/2)
  2. 按增量分组进行插入排序
  3. 逐步缩小增量直至1
public static void shellSort(int[] arr) {for(int gap=arr.length/2; gap>0; gap/=2) {for(int i=gap; i<arr.length; i++) {int temp = arr[i];int j;for(j=i; j>=gap && arr[j-gap]>temp; j-=gap) {arr[j] = arr[j-gap];}arr[j] = temp;}}
}

五、归并排序(Merge Sort)

算法逻辑

  1. 将数组递归分成两半
  2. 对子数组进行排序
  3. 合并两个有序子数组
import java.util.Arrays;public class MergeSort {public static void mergeSort(int[] arr) {if (arr == null || arr.length <= 1) return;int[] temp = new int[arr.length]; // 临时数组用于合并操作sort(arr, 0, arr.length - 1, temp);}private static void sort(int[] arr, int low, int high, int[] temp) {if (low >= high) return; // 递归终止条件int mid = low + (high - low) / 2; // 防止整数溢出sort(arr, low, mid, temp);      // 递归排序左半部分sort(arr, mid + 1, high, temp); // 递归排序右半部分merge(arr, low, mid, high, temp); // 合并两个有序区间}private static void merge(int[] arr, int low, int mid, int high, int[] temp) {int i = low;    // 左区间起始指针int j = mid + 1; // 右区间起始指针int t = 0;      // 临时数组指针// 合并两个有序区间到临时数组while (i <= mid && j <= high) {if (arr[i] <= arr[j]) {temp[t++] = arr[i++];} else {temp[t++] = arr[j++];}}// 处理剩余元素while (i <= mid) temp[t++] = arr[i++];while (j <= high) temp[t++] = arr[j++];// 将临时数组数据拷贝回原数组t = 0;while (low <= high) {arr[low++] = temp[t++];}}public static void main(String[] args) {// 测试用例int[] arr1 = {8, 4, 5, 7, 1, 3, 6, 2};mergeSort(arr1);System.out.println("排序结果 1: " + Arrays.toString(arr1)); // [1,2,3,4,5,6,7,8]int[] arr2 = {5};mergeSort(arr2);System.out.println("排序结果 2: " + Arrays.toString(arr2)); // [5]int[] arr3 = {};mergeSort(arr3);System.out.println("排序结果 3: " + Arrays.toString(arr3)); // []int[] arr4 = {9, 9, 4, 4, 2};mergeSort(arr4);System.out.println("排序结果 4: " + Arrays.toString(arr4)); // [2,4,4,9,9]int[] arr5 = {1, 2, 3, 4, 5};mergeSort(arr5);System.out.println("排序结果 5: " + Arrays.toString(arr5)); // [1,2,3,4,5]int[] arr6 = {5, 4, 3, 2, 1};mergeSort(arr6);System.out.println("排序结果 6: " + Arrays.toString(arr6)); // [1,2,3,4,5]}
}

六、快速排序(Quick Sort)

算法逻辑

  1. 选取基准元素(pivot)
  2. 将数组分为小于和大于基准的两部分
  3. 递归排序子数组
public static void quickSort(int[] arr) {quickSort(arr, 0, arr.length-1);
}private static void quickSort(int[] arr, int low, int high) {if(low < high) {int pivot = partition(arr, low, high);quickSort(arr, low, pivot-1);quickSort(arr, pivot+1, high);}
}private static int partition(int[] arr, int low, int high) {// 分区实现代码(详见完整代码)
}

七、堆排序(Heap Sort)

算法逻辑

  1. 构建最大堆
  2. 将堆顶元素与末尾元素交换
  3. 调整堆结构
  4. 重复步骤2-3
import java.util.Arrays;public class HeapSort {public static void heapSort(int[] arr) {if (arr == null || arr.length <= 1) return;// 1. 构建最大堆(从最后一个非叶子节点开始调整)int n = arr.length;for (int i = n/2 - 1; i >= 0; i--) {heapify(arr, n, i);}// 2. 逐个提取堆顶元素(最大值)for (int i = n-1; i >= 0; i--) {// 将当前堆顶(最大值)移到数组末尾swap(arr, 0, i);// 调整剩余元素重建最大堆(堆大小减1)heapify(arr, i, 0);}}// 调整以节点i为根的子树为最大堆private static void heapify(int[] arr, int heapSize, int i) {int largest = i;       // 初始化最大元素为当前根节点int left = 2 * i + 1;  // 左子节点索引int right = 2 * i + 2; // 右子节点索引// 比较左子节点与当前最大值if (left < heapSize && arr[left] > arr[largest]) {largest = left;}// 比较右子节点与当前最大值if (right < heapSize && arr[right] > arr[largest]) {largest = right;}// 如果最大值不是根节点,则交换并递归调整if (largest != i) {swap(arr, i, largest);heapify(arr, heapSize, largest);}}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void main(String[] args) {// 测试用例int[] arr1 = {4, 10, 3, 5, 1};heapSort(arr1);System.out.println("排序结果 1: " + Arrays.toString(arr1)); // [1,3,4,5,10]int[] arr2 = {12};heapSort(arr2);System.out.println("排序结果 2: " + Arrays.toString(arr2)); // [12]int[] arr3 = {};heapSort(arr3);System.out.println("排序结果 3: " + Arrays.toString(arr3)); // []int[] arr4 = {5, 5, 3, 3, 2};heapSort(arr4);System.out.println("排序结果 4: " + Arrays.toString(arr4)); // [2,3,3,5,5]int[] arr5 = {1, 2, 3, 4, 5};heapSort(arr5);System.out.println("排序结果 5: " + Arrays.toString(arr5)); // [1,2,3,4,5]int[] arr6 = {9, 7, 5, 3, 1};heapSort(arr6);System.out.println("排序结果 6: " + Arrays.toString(arr6)); // [1,3,5,7,9]}
}

八、桶排序(Bucket Sort)

算法逻辑

  1. 创建若干空桶
  2. 将元素分配到对应区间桶中
  3. 对每个非空桶排序
  4. 合并所有桶元素
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;public class BucketSort {public static void bucketSort(int[] arr) {if (arr == null || arr.length == 0) {return;}// 确定最大值和最小值int min = arr[0];int max = arr[0];for (int num : arr) {if (num < min) {min = num;} else if (num > max) {max = num;}}// 所有元素相等,无需排序if (max == min) {return;}// 初始化桶int bucketCount = arr.length;ArrayList<ArrayList<Integer>> buckets = new ArrayList<>(bucketCount);for (int i = 0; i < bucketCount; i++) {buckets.add(new ArrayList<>());}// 将元素分配到桶中for (int num : arr) {// 计算桶的索引,确保均匀分布int bucketIndex = ((num - min) * (bucketCount - 1)) / (max - min);buckets.get(bucketIndex).add(num);}// 对每个桶进行排序并合并int index = 0;for (ArrayList<Integer> bucket : buckets) {Collections.sort(bucket); // 使用内置排序算法for (int num : bucket) {arr[index++] = num;}}}public static void main(String[] args) {int[] arr1 = {3, 1, 4, 2, 5};bucketSort(arr1);System.out.println("排序结果 1: " + Arrays.toString(arr1));int[] arr2 = {5, 3, 9, 1, 7};bucketSort(arr2);System.out.println("排序结果 2: " + Arrays.toString(arr2));int[] arr3 = {9, 5, 7, 3, 2, 1};bucketSort(arr3);System.out.println("排序结果 3: " + Arrays.toString(arr3));int[] arr4 = {1, 0, 100, 50};bucketSort(arr4);System.out.println("排序结果 4: " + Arrays.toString(arr4));}
}

九、计数排序(Counting Sort)

算法逻辑

  1. 统计元素出现次数
  2. 计算元素正确位置
  3. 反向填充目标数组
public static void countingSort(int[] arr) {int max = Arrays.stream(arr).max().getAsInt();int[] count = new int[max+1];// 统计频率for(int num : arr) count[num]++;// 计算位置for(int i=1; i<count.length; i++) {count[i] += count[i-1];}// 构建结果数组int[] output = new int[arr.length];for(int i=arr.length-1; i>=0; i--) {output[--count[arr[i]]] = arr[i];}System.arraycopy(output, 0, arr, 0, arr.length);
}

十、基数排序(Radix Sort)

算法逻辑

  1. 从低位到高位依次排序
  2. 使用稳定排序算法(通常为计数排序)
  3. 逐位排序直到最高位
public static void radixSort(int[] arr) {int max = Arrays.stream(arr).max().getAsInt();for(int exp=1; max/exp>0; exp*=10) {countingSortByDigit(arr, exp);}
}private static void countingSortByDigit(int[] arr, int exp) {// 按指定位进行计数排序
}

总结对比表

排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
冒泡排序O(n²)O(n)O(n²)O(1)稳定
选择排序O(n²)O(n²)O(n²)O(1)不稳定
插入排序O(n²)O(n)O(n²)O(1)稳定
希尔排序O(n log n)O(n log²n)O(n²)O(1)不稳定
归并排序O(n log n)O(n log n)O(n log n)O(n)稳定
快速排序O(n log n)O(n log n)O(n²)O(log n)不稳定
堆排序O(n log n)O(n log n)O(n log n)O(1)不稳定
桶排序O(n+k)O(n+k)O(n²)O(n+k)稳定
计数排序O(n+k)O(n+k)O(n+k)O(k)稳定
基数排序O(n*k)O(n*k)O(n*k)O(n+k)稳定

注:k为桶的数量或数值范围

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

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

相关文章

【Clang AST】基于 Clang 获取分析 AST

The Clang AST AST&#xff08;Abstract Syntax Tree&#xff09;抽象语法树 AST是什么 抽象语法树&#xff08;Abstract Syntax Tree, AST&#xff09;是源代码的抽象表示&#xff0c;广泛用于编译器和分析工具中。 AST将源代码的语法结构转换为树形结构&#xff0c;其中每…

onedav一为导航批量自动化导入网址(完整教程)

OneNav作为一个功能强大的导航工具,支持后台管理、加密链接、浏览器书签批量导入等功能,能够帮助用户轻松打造专属的导航页面。今天,我将为大家详细介绍如何实现OneNav导航站的批量自动化导入网址。 1、建立要批量导入的表格 格局需要创建表格,表格的要求是一定要有需要,…

文档处理控件Aspose.Words 教程:.NET版中增强的 AI 文档摘要功能

Aspose.Words是一个功能强大的 Word 文档处理库。它可以帮助开发人员自动编辑、转换和处理文档。 自 24.11 版以来&#xff0c;Aspose.Words for .NET 提供了 AI 驱动的文档摘要功能&#xff0c;使用户能够从冗长的文本中快速提取关键见解。在 25.2 版中&#xff0c;我们通过使…

AI本地部署之dify

快捷目录 Windows 系统一、环境准备:首先windows 需要准备docker 环1. 安装Docker desktop2. 安装Docker3. 配置Docker 镜像路径4. 配置Docker 下载镜像源5. 重启Docker服务二、Dify 下载和安装1. Dify下载2. Dify 配置3. Dify 安装附件知识:4. Dify创建账号三、下载Ollama d…

DDS协议(二)

一、DDS发布订阅机制 基于发布/订阅的数据分发服务为各种虚拟机载设备之间的通信提供了统一的底层支撑 其技术原理如图所示&#xff1a; 发布方应用程序和订阅方应用程序分别同发布/订阅中间件通信&#xff0c; 而数据的实际分发是由发布/订阅中间件来处理。 发布方将包含主题…

GitHub供应链攻击事件:Coinbase遭袭,218个仓库暴露,CI/CD密钥泄露

此次供应链攻击涉及GitHub Action "tj-actions/changed-files"&#xff0c;最初是针对Coinbase的一个开源项目的高度定向攻击&#xff0c;随后演变为范围更广的威胁。 攻击过程与影响 Palo Alto Networks Unit 42在一份报告中指出&#xff1a;“攻击载荷主要针对其…

transform

http://zhihu.com/question/445556653/answer/3254012065 西科技的文章 视频讲解 小白也能听懂的 transformer模型原理详解 self- attention 多头注意力机制 encoder decoder 机器翻译_哔哩哔哩_bilibili

Spring Boot 整合 Nacos 注册中心终极指南

在微服务架构中&#xff0c;配置管理和动态路由是核心需求。Nacos 作为阿里巴巴开源的动态服务发现、配置管理和服务管理平台&#xff0c;能够帮助开发者实现配置热更新、多环境共享配置以及动态路由管理。本文将结合 Spring Boot 和 Spring Cloud Gateway&#xff0c;手把手教…

网络基础梳理

为什么要有网络呢&#xff1f; 在一开始科学家们都是自己在计算机当中做实验但是难免需要共同进行科研。假设现在一个业务需要三个人共同完成&#xff0c;那么现在就有问题了&#xff1a; 由于第一个人完成工作前&#xff0c;其他两人无法开始&#xff0c;这导致工作流程是串行…

EMS小车技术特点与优势:高效灵活的自动化输送解决方案

北成新控伺服技术丨EMS小车调试视频 EMS小车是一种基于单轨运行的电动输送系统&#xff0c;通过电力驱动实现物料的高效搬运和输送&#xff0c;具有高效灵活、节能环保、多功能集成、行业适配性强等特性&#xff0c;广泛应用于汽车制造、工程机械、家电生产、仓储物流等行业自动…

Python实现deepseek接口的调用

简介&#xff1a;DeepSeek 是一个强大的大语言模型&#xff0c;提供 API 接口供开发者调用。在 Python 中&#xff0c;可以使用 requests 或 httpx 库向 DeepSeek API 发送请求&#xff0c;实现文本生成、代码补全&#xff0c;知识问答等功能。本文将介绍如何在 Python 中调用 …

2025清华大学:DeepSeek教程全集(PDF+视频精讲,共10份).zip

一、资料列表 第一课&#xff1a;Deepseek基础入门 第二课&#xff1a;DeepSeek赋能职场 第三课&#xff1a;普通人如何抓住DeepSeek红利 第四课&#xff1a;让科研像聊天一样简单 第五课&#xff1a;DeepSeek与AI幻觉 第六课&#xff1a;基于DeepSeek的AI音乐词曲的创造法 第…

“智改数转”新风口,物联网如何重构制造业竞争力?

一、政策背景 为深化制造业智能化改造、数字化转型、网络化联接&#xff0c;江苏省制定了《江苏省深化制造业智能化改造数字化转型网络化联接三年行动计划&#xff08;2025&#xff0d;2027年&#xff09;》&#xff0c;提出到2027年&#xff0c;全省制造业企业设备更新、工艺…

OpenHarmony 入门——ArkUI 跨页面数据同步和页面级UI状态存储LocalStorage小结(二)

文章大纲 引言一、在代码逻辑使用LocalStorage二、从UI内部使用LocalStorage三、LocalStorageProp和LocalStorage单向同步四、LocalStorageLink和LocalStorage双向同步五、兄弟组件之间同步状态变量七、将LocalStorage实例从UIAbility共享到一个或多个视图 引言 前面一篇文章主…

干货分享|DeepSeek技术革命、算力范式重构与场景落地洞察

本文为TsingtaoAI公司负责人汶生为某证券公司管理层和投资者教授的《DeepSeek技术革命、算力范式重构与场景落地洞察》主题培训内容&#xff0c;此次主题培训系统阐述了当前AI技术演进的核心趋势、算力需求的结构性变革&#xff0c;以及行业应用落地的关键路径。 现在我们将全…

从切图仔到鸿蒙开发01-文本样式

从切图仔到鸿蒙开发01-文本样式 本系列教程适合 HarmonyOS 初学者&#xff0c;为那些熟悉用 HTML 与 CSS 语法的 Web 前端开发者准备的。 本系列教程会将 HTML/CSS 代码片段替换为等价的 HarmonyOS/ArkUI 代码。 页面结构 HTML 与 ArkUI 在 Web 开发中&#xff0c;HTML 文档结…

零基础入门网络爬虫第5天:Scrapy框架

4周 Srapy爬虫框架 不是一个简单的函数功能库&#xff0c;而是一个爬虫框架 安装&#xff1a;pip install scrapy 检测&#xff1a;scrapy -h Scrapy爬虫框架结构 爬虫框架 爬虫框架是实现爬虫功能的一个软件结构和功能组件集合爬虫框架是一个半成品&#xff0c;能够帮助…

C语言:扫雷

在编程的世界里&#xff0c;扫雷游戏是一个经典的实践项目。它不仅能帮助我们巩固编程知识&#xff0c;还能锻炼逻辑思维和解决问题的能力。今天&#xff0c;就让我们一起用 C 语言来实现这个有趣的游戏&#xff0c;并且通过图文并茂的方式&#xff0c;让每一步都清晰易懂 1. 游…

同一个局域网的话 如何访问另一台电脑的ip

在局域网内访问另一台电脑&#xff0c;可以通过以下几种常见的方法来实现&#xff1a; ‌直接通过IP地址访问‌&#xff1a; 首先&#xff0c;确保两台电脑都连接在同一个局域网内。获取目标电脑的IP地址&#xff0c;这可以通过在目标电脑上打开命令提示符&#xff08;Windows系…

记录我的ICME2025论文之旅:困顿与收获

人生第一次中B会&#xff0c;还是在课业繁重的大三上&#xff08;有点说法~&#xff09; “在最黑暗的时刻&#xff0c;总有一束光为你指引前行。” ——记录这段难忘的历程 今年的ICME投稿量创下新高&#xff0c;录取率却跌至20多%&#xff0c;并且首次加入了rebuttal&#xf…