0

0

Java中如何对数组进行快速排序

尼克

尼克

发布时间:2025-06-26 21:55:02

|

709人浏览过

|

来源于php中文网

原创

快速排序的核心是分而治之,通过选择基准值将数组分为两部分并递归排序。1. 选取基准值(如随机选择或三数取中法);2. 分区操作使小于基准值的元素在左、大于的在右;3. 递归对左右子数组排序。为优化性能,可对小数组切换插入排序。相比归并排序,快速排序原地排序且平均性能更优,但不稳定且最坏时间复杂度为o(n^2)。

Java中如何对数组进行快速排序

Java中快速排序数组的核心在于分而治之的思想。简单来说,就是选取一个基准值,将数组分成两部分,一部分小于基准值,一部分大于基准值,然后递归地对这两部分进行排序。

Java中如何对数组进行快速排序

解决方案

Java中如何对数组进行快速排序

快速排序是一种高效的排序算法,尤其适用于大型数据集。以下是在Java中实现快速排序的步骤和代码示例:

立即学习Java免费学习笔记(深入)”;

Java中如何对数组进行快速排序
  1. 选择基准值(Pivot): 从数组中选择一个元素作为基准值。选择方式会影响性能,常见的有选择第一个元素、最后一个元素、中间元素或随机元素。

  2. 分区(Partitioning): 重新排列数组,所有小于基准值的元素都放在基准值之前,所有大于基准值的元素都放在基准值之后。基准值位于它最终排序后的位置。

  3. 递归排序: 递归地对基准值之前的子数组和基准值之后的子数组进行快速排序。

public class QuickSort {

    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int partitionIndex = partition(arr, low, high);

            quickSort(arr, low, partitionIndex - 1);
            quickSort(arr, partitionIndex + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = (low - 1); // Index of smaller element
        for (int j = low; j < high; j++) {
            // If current element is smaller than or equal to pivot
            if (arr[j] <= pivot) {
                i++;

                // swap arr[i] and arr[j]
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }

        // swap arr[i+1] and arr[high] (or pivot)
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;

        return i + 1;
    }

    public static void main(String[] args) {
        int[] arr = {10, 7, 8, 9, 1, 5};
        int n = arr.length;
        quickSort(arr, 0, n - 1);

        System.out.println("Sorted array:");
        for (int i = 0; i < n; ++i)
            System.out.print(arr[i] + " ");
        System.out.println();
    }
}

这段代码首先定义了一个 quickSort 方法,它接受数组、低索引和高索引作为参数。partition 方法负责将数组分成两部分,并返回基准值的索引。main 方法用于测试快速排序算法。

快速排序的关键在于 partition 函数,它通过遍历数组,将小于等于基准值的元素放到基准值的左边,大于基准值的元素放到右边。

快速排序的平均时间复杂度是 O(n log n),但在最坏情况下(例如,数组已经排序),时间复杂度会退化到 O(n^2)。为了避免最坏情况,可以采用随机选择基准值的方法。

快速排序是不稳定的排序算法,即相等元素的相对位置在排序后可能会发生改变。

快速排序通常比其他 O(n log n) 排序算法(如归并排序)更快,因为它具有较小的常数因子。

如何选择合适的基准值以优化快速排序的性能?

选择基准值是快速排序性能的关键。理想情况下,基准值应该尽可能地将数组分成大小相等的两部分。以下是一些常见的基准值选择策略:

  • 选择第一个元素或最后一个元素: 这是最简单的策略,但如果数组已经排序或接近排序,会导致最坏情况 O(n^2) 的时间复杂度。

  • 选择中间元素: 可以稍微改善性能,但仍然可能在某些情况下导致较差的性能。

    j2me3D游戏开发简单教程 中文WORD版
    j2me3D游戏开发简单教程 中文WORD版

    本文档主要讲述的是j2me3D游戏开发简单教程; 如今,3D图形几乎是任何一部游戏的关键部分,甚至一些应用程序也通过用3D形式来描述信息而获得了成功。如前文中所述,以立即模式和手工编码建立所有的3D对象的方式进行开发速度很慢且很复杂。应用程序中多边形的所有角点必须在数组中独立编码。在JSR 184中,这称为立即模式。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看

    下载
  • 随机选择: 从数组中随机选择一个元素作为基准值。这种方法可以有效地避免最坏情况,因为无论输入数组的初始状态如何,选择到坏基准值的概率都很低。

  • 三数取中(Median-of-Three): 选择数组的第一个元素、中间元素和最后一个元素,然后取这三个元素的中位数作为基准值。这种方法在实践中表现良好,因为它通常可以选到一个接近中间值的基准值。

private static int partition(int[] arr, int low, int high) {
    // 三数取中
    int mid = low + (high - low) / 2;
    int pivot = medianOfThree(arr, low, mid, high);

    // 将基准值放到high位置
    swap(arr, pivot, high);

    pivot = arr[high];
    int i = (low - 1); // Index of smaller element
    for (int j = low; j < high; j++) {
        // If current element is smaller than or equal to pivot
        if (arr[j] <= pivot) {
            i++;

            // swap arr[i] and arr[j]
            swap(arr, i, j);
        }
    }

    // swap arr[i+1] and arr[high] (or pivot)
    swap(arr, i + 1, high);

    return i + 1;
}

private static int medianOfThree(int[] arr, int a, int b, int c) {
    if ((arr[a] - arr[b]) * (arr[c] - arr[a]) >= 0) {
        return a;
    } else if ((arr[b] - arr[a]) * (arr[c] - arr[b]) >= 0) {
        return b;
    } else {
        return c;
    }
}

private static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

使用三数取中法,可以有效地减少最坏情况发生的概率,提高快速排序的整体性能。

如何处理快速排序中的小数组以提高效率?

当快速排序递归到足够小的子数组时,快速排序的优势会减弱。这是因为快速排序的递归调用和分区操作有一定的开销。对于小数组,插入排序等简单排序算法可能更有效。

一种常见的优化方法是,当子数组的大小小于某个阈值时,切换到插入排序。这个阈值通常在 5 到 20 之间,具体值取决于硬件和数据特性。

private static void quickSort(int[] arr, int low, int high) {
    int INSERTION_SORT_THRESHOLD = 10; // 阈值

    if (high - low + 1 < INSERTION_SORT_THRESHOLD) {
        insertionSort(arr, low, high);
    } else if (low < high) {
        int partitionIndex = partition(arr, low, high);

        quickSort(arr, low, partitionIndex - 1);
        quickSort(arr, partitionIndex + 1, high);
    }
}

private static void insertionSort(int[] arr, int low, int high) {
    for (int i = low + 1; i <= high; i++) {
        int key = arr[i];
        int j = i - 1;

        /* Move elements of arr[0..i-1], that are
           greater than key, to one position ahead
           of their current position */
        while (j >= low && arr[j] > key) {
            arr[j] = arr[j + 1];
            j = j - 1;
        }
        arr[j + 1] = key;
    }
}

这段代码在 quickSort 方法中添加了一个判断,如果子数组的大小小于 INSERTION_SORT_THRESHOLD,就调用 insertionSort 方法进行排序。

通过这种方式,可以避免快速排序在小数组上的低效操作,从而提高整体排序效率。

快速排序与归并排序相比,有什么优缺点?

快速排序和归并排序都是常用的 O(n log n) 排序算法,但它们在实现方式和性能特点上有所不同。

快速排序的优点:

  • 原地排序: 快速排序是一种原地排序算法,只需要很小的额外空间(通常是 O(log n) 的栈空间用于递归)。
  • 平均性能好: 在平均情况下,快速排序比归并排序更快,因为它具有较小的常数因子。
  • 缓存友好: 快速排序在内存中是连续访问数据的,因此缓存命中率较高。

快速排序的缺点:

  • 最坏情况性能差: 在最坏情况下(例如,数组已经排序),快速排序的时间复杂度会退化到 O(n^2)。
  • 不稳定: 快速排序是一种不稳定的排序算法,相等元素的相对位置在排序后可能会发生改变。

归并排序的优点:

  • 稳定: 归并排序是一种稳定的排序算法,相等元素的相对位置在排序后不会发生改变。
  • 最坏情况性能好: 归并排序的时间复杂度始终是 O(n log n),不会出现最坏情况。
  • 易于并行化: 归并排序可以很容易地并行化,从而提高排序速度。

归并排序的缺点:

  • 需要额外空间: 归并排序需要 O(n) 的额外空间用于合并操作。
  • 常数因子较大: 归并排序的常数因子比快速排序大,因此在平均情况下速度较慢。
  • 缓存不友好: 归并排序在合并过程中需要频繁地在内存中跳跃访问数据,因此缓存命中率较低。

总的来说,如果对排序的稳定性有要求,或者需要保证最坏情况下的性能,那么归并排序是一个更好的选择。如果对空间复杂度有要求,并且可以接受不稳定的排序结果,那么快速排序通常是更快的选择。

在实际应用中,可以根据具体的需求和数据特点选择合适的排序算法。有时候,也可以将快速排序和归并排序结合起来使用,例如,先使用快速排序将数组分成多个小块,然后使用归并排序将这些小块合并起来。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

841

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

742

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

738

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.7万人学习

C# 教程
C# 教程

共94课时 | 7.2万人学习

Java 教程
Java 教程

共578课时 | 48.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号