深入解析经典排序算法:原理、实现与优化

server/2024/11/28 14:46:48/

文章目录

      • 6. 堆排序(Heap Sort)
        • 原理
        • Java 实现
      • 7. 希尔排序(Shell Sort)
        • 原理
        • Java 实现
      • 8. 计数排序(Counting Sort)
        • 原理
        • Java 实现
      • 9. 基数排序(Radix Sort)
        • 原理
        • Java 实现

深入浅出:Java 中的经典算法>排序算法详解与实现

6. 堆排序(Heap Sort)

原理

算法>排序算法是一种高效的排序方法,其核心在于利用了堆的数据结构特性。堆是一种特殊的完全二叉树,可以分为最大堆和最小堆两种形式。在最大堆中,每个父节点的值总是大于或等于其两个子节点的值;而在最小堆中,每个父节点的值总是小于或等于其两个子节点的值。这种性质使得堆的根节点总是整个堆中的最大值或最小值。

算法>排序算法的过程主要分为两个阶段:

  1. 构建初始堆:首先将待排序的无序序列构建成一个最大堆(假设升序排列),此时堆顶元素即为序列中的最大值。
  2. 排序处理:将堆顶元素与序列最后一个元素交换位置,然后将剩余的序列重新调整为最大堆,重复这一过程,直到所有元素都被排序。
Java 实现
java">public class HeapSort {public static void sort(int[] arr) {int n = arr.length;// 构建最大堆for (int i = n / 2 - 1; i >= 0; i--) {heapify(arr, n, i);}// 开始排序for (int i = n - 1; i > 0; i--) {// 移动当前根节点至数组末尾int temp = arr[0];arr[0] = arr[i];arr[i] = temp;// 对剩余未排序的元素重新构建最大堆heapify(arr, i, 0);}}private static void heapify(int[] arr, int n, int i) {int largest = i; // 初始化最大值为根节点int left = 2 * i + 1; // 左子节点int right = 2 * i + 2; // 右子节点// 比较左子节点是否大于根节点if (left < n && arr[left] > arr[largest]) {largest = left;}// 比较右子节点是否大于当前最大值if (right < n && arr[right] > arr[largest]) {largest = right;}// 若最大值不是根节点,则交换它们的位置,并继续向下调整if (largest != i) {int swap = arr[i];arr[i] = arr[largest];arr[largest] = swap;heapify(arr, n, largest);}}
}

7. 希尔排序(Shell Sort)

原理

希尔排序是对直接插入排序的优化,它通过将原始列表分割成多个子列表,每个子列表分别进行插入排序,这样做的目的是为了减少数据项之间的移动次数,从而提高排序效率。希尔排序的关键在于选择合适的间隔序列,间隔序列的选择直接影响到排序的性能。

Java 实现
java">public class ShellSort {public static void sort(int[] arr) {int n = arr.length;int gap = n / 2;// 控制间隔序列while (gap > 0) {for (int i = gap; i < n; i++) {int temp = arr[i];int j = i;// 插入排序的核心部分,使用间隔进行比较和交换while (j >= gap && arr[j - gap] > temp) {arr[j] = arr[j - gap];j -= gap;}arr[j] = temp;}// 减小间隔gap /= 2;}}
}

8. 计数排序(Counting Sort)

原理

计数排序是一种线性时间复杂度的非比较型算法>排序算法,特别适合用于数据范围已知且较小的情况。它的工作原理是创建一个额外的计数数组来记录输入数组中每个元素出现的次数,然后根据计数数组重构出排序后的数组。

Java 实现
java">public class CountingSort {public static void sort(int[] arr) {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 range = max - min + 1;int[] count = new int[range];// 计算每个元素出现的次数for (int num : arr) {count[num - min]++;}// 重构排序后的数组int index = 0;for (int i = 0; i < range; i++) {while (count[i] > 0) {arr[index++] = i + min;count[i]--;}}}
}

9. 基数排序(Radix Sort)

原理

基数排序是一种非比较型的算法>排序算法,主要用于整数排序。它通过对整数的每一位数字进行独立的排序来实现整体排序的目的。基数排序有两种主要的方式:最高有效位(MSD)和最低有效位(LSD)。LSD 方法通常更常用,因为它可以通过简单的计数排序或桶排序来实现。

基数排序的基本步骤包括:

  1. 确定排序的最大位数:找到数组中的最大值,以确定需要排序的位数。
  2. 按位排序:从最低位开始,对每一位上的数字进行排序,通常使用计数排序作为子过程。
  3. 合并结果:经过多次按位排序后,数组已经是有序状态。
Java 实现
java">public class RadixSort {public static void sort(int[] arr) {int max = getMax(arr); // 获取数组中最大的数// 对每个位数进行排序for (int exp = 1; max / exp > 0; exp *= 10) {countSort(arr, exp);}}private static void countSort(int[] arr, int exp) {int n = arr.length;int[] output = new int[n]; // 输出数组int[] count = new int[10]; // 计数数组// 计算每个位数上的数字出现次数for (int i = 0; i < n; i++) {int index = (arr[i] / exp) % 10;count[index]++;}// 修改 count 数组,使其包含实际位置信息for (int i = 1; i < 10; i++) {count[i] += count[i - 1];}// 构建输出数组for (int i = n - 1; i >= 0; i--) {int index = (arr[i] / exp) % 10;output[count[index] - 1] = arr[i];count[index]--;}// 将输出数组复制回原数组for (int i = 0; i < n; i++) {arr[i] = output[i];}}private static int getMax(int[] arr) {int max = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}return max;}
}

这些算法>排序算法各有特点,适用于不同场景下的排序需求。在选择算法>排序算法时,应考虑数据的具体特征、大小以及性能要求等因素。


http://www.ppmy.cn/server/145650.html

相关文章

(STM32)ADC驱动配置

1.ADC驱动&#xff08;STM32&#xff09; ADC模块中&#xff0c;**常规模式&#xff08;Regular Mode&#xff09;和注入模式&#xff08;Injected Mode&#xff09;**是两种不同的ADC工作模式 常规模式&#xff1a;用于普通的ADC转换&#xff0c;是默认的ADC工作模式。 注入…

【ROS2】ROS2 与 ROS1 编码方式对比(C++实现)

目录 一、初始化和关闭节点二、发布者和订阅者三、服务和客户端四、参数管理五、日志记录六、生命周期管理 ROS1 主要使用roscpp和rospy作为客户端库&#xff0c;分别用于C和Python语言。 ROS2 引入了新的客户端库rclcpp&#xff08;C&#xff09;和rclpy&#xff08;Python&a…

iOS开发之修改已有项目的项目名和类名前缀

一、修改项目名称 1、Xcode打开项目修改项目名称 直接选中项目&#xff0c;点击enter&#xff0c;直接修改项目名称 把buydodo改成xiedodo&#xff0c;点击enter Rename完了点继续&#xff0c;只有框框内的部分变了 2、退出Xcode关闭项目&#xff0c;修改剩下的项目名称 找…

论文笔记(五十七)Diffusion Model Predictive Control

Diffusion Model Predictive Control 文章概括摘要1. Introduction2. Related work3. 方法3.1 模型预测控制3.2. 模型学习3.3. 规划&#xff08;Planning&#xff09;3.4. 适应 4. 实验&#xff08;Experiments&#xff09;4.1. 对于固定奖励&#xff0c;D-MPC 可与其他离线 RL…

element-plus弹窗二次封装踩坑

1 基于element-plus的二次封装弹窗很常见。代码如下&#xff1a; 父组件&#xff1a; import Dialog from ./components/Dialogs/testDailog.vueconst showref(false) const openDialog()>{show.valuetrue}<button click"openDialog" >打开dialoag</bu…

git merge 排除文件

方法一&#xff1a; 在Git中&#xff0c;如果你想在合并时排除特定文件&#xff0c;你可以使用.gitattributes文件来指定合并策略。你可以设置一个自定义合并策略来忽略特定文件的合并。 首先&#xff0c;在仓库的根目录下创建或编辑.gitattributes文件&#xff0c;并添加以…

微服务上下线动态感知实现的技术解析

序言 随着微服务架构的广泛应用&#xff0c;服务的动态管理和监控变得尤为重要。在微服务架构中&#xff0c;服务的上下线是一个常见的操作&#xff0c;如何实时感知这些变化&#xff0c;确保系统的稳定性和可靠性&#xff0c;成为了一个关键技术挑战。本文将深入探讨微服务上…

【C++】string类练习

test1:反转字母 给你一个字符串 s &#xff0c;根据下述规则反转字符串&#xff1a; 所有非英文字母保留在原有位置。所有英文字母&#xff08;小写或大写&#xff09;位置反转。 返回反转后的 s 。 示例 1&#xff1a; 输入&#xff1a;s "ab-cd" 输出&#xff1a;…