java-快速排序 1

## Java中的快速排序

### 1. 快速排序的基本概念

快速排序(Quick Sort)是一种高效的排序算法,由Tony Hoare在1960年提出。它采用分治法(Divide and Conquer)策略来将一个数组分成较小的子数组,并分别对它们进行排序。快速排序通常被认为是最实用的排序算法之一,因为它在大多数情况下具有非常好的平均性能。

### 2. 快速排序的工作原理

快速排序的核心思想是通过一个称为“基准”(Pivot)的元素将数组分为两部分,使得基准左侧的元素都小于基准,右侧的元素都大于基准。然后,递归地对左右两部分进行同样的操作,直到整个数组有序。

#### 2.1 分治法

快速排序使用分治法,将问题递归地分解成更小的子问题。具体步骤如下:

1. **选择基准**:从数组中选择一个元素作为基准,通常选择第一个元素或最后一个元素。
2. **划分数组**:重排数组,使得基准左侧的元素都小于基准,右侧的元素都大于基准。
3. **递归排序**:递归地对基准左侧和右侧的子数组进行排序。

#### 2.2 示例

假设有一个待排序的数组 `[10, 7, 8, 9, 1, 5]`,快速排序的过程如下:

1. 选择基准元素,假设选择最后一个元素 `5`。
2. 划分数组,将小于 `5` 的元素移到左侧,大于 `5` 的元素移到右侧,得到 `[1, 7, 8, 9, 10, 5]`。
3. 基准 `5` 已经在正确的位置,现在对左侧 `[1, 7, 8, 9, 10]` 和右侧空数组进行递归排序。
4. 重复上述步骤,直到数组有序。

### 3. 快速排序的实现

在Java中实现快速排序可以使用递归方法,下面是详细的实现步骤。

#### 3.1 基本实现

```java
public class QuickSort {

    // 快速排序主方法
    public static void quickSort(int[] array, int low, int high) {
        if (low < high) {
            // 找到划分点
            int pi = partition(array, low, high);
            // 递归排序划分点左侧的数组
            quickSort(array, low, pi - 1);
            // 递归排序划分点右侧的数组
            quickSort(array, pi + 1, high);
        }
    }

    // 划分方法
    private static int partition(int[] array, int low, int high) {
        int pivot = array[high]; // 选择最后一个元素作为基准
        int i = low - 1; // i指向小于基准的区域的最后一个元素

        for (int j = low; j < high; j++) {
            if (array[j] < pivot) {
                i++;
                // 交换元素
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
        // 交换基准元素到正确的位置
        int temp = array[i + 1];
        array[i + 1] = array[high];
        array[high] = temp;

        return i + 1;
    }

    public static void main(String[] args) {
        int[] array = {10, 7, 8, 9, 1, 5};
        quickSort(array, 0, array.length - 1);
        System.out.println("Sorted array:");
        for (int i : array) {
            System.out.print(i + " ");
        }
    }
}
```

在这个实现中,`quickSort`方法是快速排序的主方法,它递归地对数组进行排序。`partition`方法是划分数组的方法,它选择一个基准元素,并将数组划分为两部分。

### 4. 快速排序的时间复杂度

快速排序的时间复杂度取决于选择基准的策略和输入数组的初始顺序:

- **最好情况**:每次划分都能将数组均匀地分成两部分,时间复杂度为 O(n log n)。
- **最坏情况**:每次划分只能减少一个元素,例如输入数组已经有序或逆序,时间复杂度为 O(n^2)。
- **平均情况**:通过随机选择基准或三数取中法等策略,可以避免最坏情况,平均时间复杂度为 O(n log n)。

### 5. 快速排序的空间复杂度

快速排序的空间复杂度主要由递归调用栈的深度决定:

- **最好情况**:递归调用栈的深度为 O(log n)。
- **最坏情况**:递归调用栈的深度为 O(n)。
- **平均情况**:递归调用栈的深度为 O(log n)。

### 6. 快速排序的优化

为了提高快速排序的性能,可以进行以下优化:

#### 6.1 三数取中法

选择基准时,使用三数取中法可以避免选择最小或最大的元素作为基准,从而避免最坏情况。

```java
private static int medianOfThree(int[] array, int low, int high) {
    int mid = (low + high) / 2;
    if (array[low] > array[mid]) swap(array, low, mid);
    if (array[low] > array[high]) swap(array, low, high);
    if (array[mid] > array[high]) swap(array, mid, high);
    return array[mid];
}

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

private static int partition(int[] array, int low, int high) {
    int pivot = medianOfThree(array, low, high);
    int i = low - 1;
    for (int j = low; j < high; j++) {
        if (array[j] < pivot) {
            i++;
            swap(array, i, j);
        }
    }
    swap(array, i + 1, high);
    return i + 1;
}
```

#### 6.2 随机选择基准

随机选择基准可以避免最坏情况的发生,保证平均时间复杂度为 O(n log n)。

```java
private static int partition(int[] array, int low, int high) {
    int pivotIndex = low + (int)(Math.random() * (high - low + 1));
    swap(array, pivotIndex, high);
    int pivot = array[high];
    int i = low - 1;
    for (int j = low; j < high; j++) {
        if (array[j] < pivot) {
            i++;
            swap(array, i, j);
        }
    }
    swap(array, i + 1, high);
    return i + 1;
}
```

### 7. 快速排序的稳定性

快速排序不是一个稳定的排序算法,因为在划分过程中,相等元素的相对顺序可能会改变。然而,快速排序可以通过一些改进来实现稳定性,但这通常会增加算法的复杂性和开销。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【大模型】大模型微调方法总结(四)

1. P-Tuning v1 1.背景 大模型的Prompt构造方式严重影响下游任务的效果。比如&#xff1a;GPT-3采用人工构造的模版来做上下文学习&#xff08;in context learning&#xff09;&#xff0c;但人工设计的模版的变化特别敏感&#xff0c;加一个词或者少一个词&#xff0c;或者变…

DIY:在您的 PC 上本地使用 Stable Diffusion AI 模型生成图像

前言 随着DALL-E-2和Midjourney的发布&#xff0c;您可能听说过最近 AI 生成艺术的繁荣。这些人工智能模型如何在几秒钟内创造性地生成逼真的图像&#xff0c;这绝对是令人兴奋的。您可以在这里查看其中的一些&#xff1a;DALL-E-2 gallery和Midjourney gallery 但是这些模型…

DAY16-力扣刷题

1.不同的二叉搜索树2 95. 不同的二叉搜索树 II - 力扣&#xff08;LeetCode&#xff09; 给你一个整数 n &#xff0c;请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。 方法一&#xff1a;回溯 class Solutio…

聚观早报 | iPhone 16核心硬件曝光;三星Galaxy全球新品发布会

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 6月28日消息 iPhone 16核心硬件曝光 三星Galaxy全球新品发布会 苹果正多方下注布局AI商店 黄仁勋2024年薪酬3400…

Kotlin设计模式:深入理解桥接模式

Kotlin设计模式&#xff1a;深入理解桥接模式 在软件开发中&#xff0c;随着系统需求的不断增长和变化&#xff0c;类的职责可能会变得越来越复杂&#xff0c;导致代码难以维护和扩展。桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过…

Nest 的 IoC 机制

后端系统中&#xff0c;会有很多对象&#xff1a; Controller 对象&#xff1a;接收 http 请求&#xff0c;调用 Service&#xff0c;返回响应 Service 对象&#xff1a;实现业务逻辑 Repository 对象&#xff1a;实现对数据库的增删改查 此外&#xff0c;还有数据库链接对…

【吊打面试官系列-MyBatis面试题】MyBatis 框架的缺点?

大家好&#xff0c;我是锋哥。今天分享关于 【MyBatis 框架的缺点&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; MyBatis 框架的缺点&#xff1f; 1、SQL 语句的编写工作量较大&#xff0c;尤其当字段多、关联表多时&#xff0c;对开发人员编写 SQL 语句的功底…

工作备忘录哪个好用 好用的工作备忘录

在繁忙的工作环境中&#xff0c;备忘录就像是我手中的一把利剑&#xff0c;助我斩断杂乱的思绪&#xff0c;让工作变得井井有条。每当任务堆积如山&#xff0c;或是灵感与琐事交织时&#xff0c;我总会依赖我的备忘录来帮我理清头绪。 想象一下&#xff0c;你正忙于一个大型项…

小区物业管理收费系统源码小程序

便捷、透明、智能化的新体验 一款基于FastAdminUniApp开发的一款物业收费管理小程序。包含房产管理、收费标准、家属管理、抄表管理、在线缴费、业主公告、统计报表、业主投票、可视化大屏等功能。为物业量身打造的小区收费管理系统&#xff0c;贴合物业工作场景&#xff0c;轻…

RabbitMQ实践——搭建单人聊天服务

大纲 创建Core交换器用户登录发起聊天邀请接受邀请聊天实验过程总结代码工程 经过之前的若干节的学习&#xff0c;我们基本掌握了Rabbitmq各个组件和功能。本文我们将使用之前的知识搭建一个简单的单人聊天服务。 基本结构如下。为了避免Server有太多连线导致杂乱&#xff0c;下…

【MySQL基础篇】概述及SQL指令:DDL及DML

数据库是一个按照数据结构来组织、存储和管理数据的仓库。以下是对数据库概念的详细解释&#xff1a;定义与基本概念&#xff1a; 数据库是长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。 数据库不仅仅是数据的简单堆积&#xff0c;而是遵循一定的规则…

可用的搜索引擎

presearchhttps://presearch.com/yandexhttps://yandex.com/ 以上&#xff0c;目前均不需科学上网。

GEOS学习笔记(一)

下载编译GEOS 从Download and Build | GEOS (libgeos.org)下载geos-3.10.6.tar.bz2 使用cmake-3.14.0版本配置VS2015编译 按默认配置生成VS工程文件 编译后生成geos.dll&#xff0c;geos_c.dll 后面学习使用C接口进行编程

PCB在工业领域的应用以及人工智能的影响。

什么是pcb呢? PCB,全称Printed Circuit Board,中文名称为印制电路板,也被称为印刷线路板或印制板1。这是一种重要的电子部件,主要由绝缘基板、连接导线和装配焊接电子元器件的焊盘组成。PCB的主要作用是作为电子元器件的支撑体和电气连接的载体,它能够简化电子产品的装配…

三分钟快速搭建基于FastAPI的AI Agent应用!

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案…

【鸿蒙学习笔记】页面和自定义组件生命周期

官方文档&#xff1a;页面和自定义组件生命周期 目录标题 [Q&A] 都谁有生命周期&#xff1f; [Q&A] 什么是组件生命周期&#xff1f; [Q&A] 什么是组件&#xff1f;组件生命周期 [Q&A] 什么是页面生命周期&#xff1f; [Q&A] 什么是页面&#xff1f;页面生…

代码随想录算法训练营第五十二天| [KC]100. 岛屿的最大面积、101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题

[KamaCoder] 100. 岛屿的最大面积 [KamaCoder] 100. 岛屿的最大面积 文章解释 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;计算岛屿的最大面积。岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿由水平方向或垂直…

开放式耳机哪个牌子好?2024热门红榜开放式耳机测评真实篇!

当你跟朋友们聊天时&#xff0c;他们经常抱怨说长时间戴耳机会令耳朵感到不适,后台也有很多人来滴滴我&#xff0c;作为一位致力于开放式耳机的测评博主&#xff0c;在对比了多款开放式耳机之后&#xff0c;你开放式耳机在保护听力方面确实有用。开放式的设计有助于减轻耳道内的…

自适应蚁群算法优化的攀爬机器人的路径规划

大家好&#xff0c;我是带我去滑雪&#xff01; 攀爬机器人是一种能够在复杂环境中自主移动和攀爬的具有广阔应用前景的智能机器人&#xff0c;具有较强的应用潜力和广泛的研究价值。随着科技的不断发展&#xff0c;攀爬机器人在许多领域中的应用越来越广泛&#xff0c;例如建筑…

FastGPT 手动部署错误:MongooseServerSelectionError: getaddrinfo EAI_AGAIN mongo

在运行 FastGPT 时&#xff0c;mongodb 报如下错误&#xff1a; MongooseServerSelectionError: getaddrinfo EAI_AGAIN mongo 这是因为 mongo 没有解析出来&#xff0c;在 hosts 文件中添加如下信息&#xff1a; 127.0.0.1 mongo 重新运行 FastGPT 即可。 参考链接&#xff…