您当前的位置:首页 > 电脑百科 > 程序开发 > 算法

数据结构与算法:快速排序

时间:2023-03-07 13:53:21  来源:今日头条  作者:

一、定义

同冒泡排序一样,快速排序也属于交换排序,通过元素之间的比较和交换位置来达到排序的目的。

不同的是,冒泡排序在每一轮中只把1个元素冒泡到数列的一端,而快速排序则在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成两个部分。

这种思路就叫作分治法。

 

 

 

二、思路

1、基准元素的选择

基准元素,英文是pivot,在分治过程中,以基准元素为中心,把其他元素移动到它的左右两边 我们可以随机选择一个元素作为基准元素,并且让基准元素和数列首元素交换位置。

 

 

2、元素的比较

选定了基准元素以后,我们要做的就是把其他元素中小于基准元素的都交换到基准元素一边,大于基准元素的都交换到基准元素另一边。

(1)双边循环法

首先,选定基准元素pivot,并且设置两个指针left和right,指向数列的最左和最右两个元素

 

 

接下来进行第1次循环:

从right指针开始,让指针所指向的元素和基准元素做比较。

如果大于或等于pivot,则指针向左移动;

如果小于pivot,则right指针停止移动,切换到left指针;

轮到left指针行动,让指针所指向的元素和基准元素做比较。

如果小于或等于pivot,则指针向右移动;

如果大于pivot,则left指针停止移动 左右指针指向的元素交换位置。

由于left开始指向的是基准元素,判断肯定相等,所以left右移1位。

 

 

由于7>4,left指针在元素7的位置停下。这时,让left和right指针所指向的元素进行交换。

 

 

接下来,进入第2次循环,重新切换到right指针,向左移动。right指针先移动到8,8>4,继续左移。由于2<4,停止在2的位置。

 

 

(2)单边循环法

单边循环法只从数组的一边对元素进行遍历和交换。

开始和双边循环法相似,首先选定基准元素pivot。

同时,设置一个mark指针指向数列起始位置, 这个mark指针代表小于基准元素的区域边界。

 

 

接下来,从基准元素的下一个位置开始遍历数组。

如果遍历到的元素大于基准元素,就继续往后遍历 如果遍历到的元素小于基准元素,

则需要做两件事:

第一,把mark指针右移1位,因为小于pivot的区域边界增大了1;

第二,让最新遍历到的元素和mark指针所在位置的元素交换位置,

因为最新遍历的元素归属于小 于pivot的区域 首先遍历到元素7,7>4,所以继续遍历。

 

 

接下来遍历到的元素是3,3<4,所以mark指针右移1位

 

 

随后,让元素3和mark指针所在位置的元素交换,因为元素3归属于小于pivot的区域。

 

 

按照这个思路,继续遍历,后续步骤如图所示

 

 

三、代码实现

 

 

1、双边循环法

 

import JAVA.util.Arrays;

/**
 * 快速排序:双边循环法
 */
public class QuickSort {
    public static void quickSort(int[] arr, int startIndex,
                                 int endIndex) {
        // 递归结束条件:startIndex大于或等于endIndex时
        if (startIndex >= endIndex) {
            return;
        }
        // 得到基准元素位置
        int pivotIndex = partition(arr, startIndex, endIndex);
        // 根据基准元素,分成两部分进行递归排序
        quickSort(arr, startIndex, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, endIndex);
    }

    /**
     * 分治(双边循环法)
     *
     * @param arr        待交换的数组
     * @param startIndex 起始下标
     * @param endIndex   结束下标
     * @return
     */
    private static int partition(int[] arr, int startIndex, int endIndex) {
        // 取第1个位置(也可以选择随机位置)的元素作为基准元素
        int pivot = arr[startIndex];
        int left = startIndex;
        int right = endIndex;
        while (left != right) {
        //控制right 指针比较并左移
            while (left < right && arr[right] > pivot) {
                right--;
            }
        //控制left指针比较并右移
            while (left < right && arr[left] <= pivot) {
                left++;
            }
        //交换left和right 指针所指向的元素
            if (left < right) {
                int p = arr[left];
                arr[left] = arr[right];
                arr[right] = p;
            }
        }
        //pivot 和指针重合点交换
        arr[startIndex] = arr[left];
        arr[left] = pivot;
        return left;
    }

    public static void mAIn(String[] args) {
        int[] arr = new int[]{4, 7, 3, 5, 6, 2, 8, 1};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
}
 

2、单边循环法

import java.util.Arrays;

/**
 * 快速排序:单边循环法
 */
public class QuickSort {
    public static void quickSort(int[] arr, int startIndex,
                                 int endIndex) {
        // 递归结束条件:startIndex大于或等于endIndex时
        if (startIndex >= endIndex) {
            return;
        }
        // 得到基准元素位置
        int pivotIndex = partition(arr, startIndex, endIndex);
        // 根据基准元素,分成两部分进行递归排序
        quickSort(arr, startIndex, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, endIndex);
    }

    /**
     * 分治(单边循环法)
     *
     * @param arr        待交换的数组
     * @param startIndex 起始下标
     * @param endIndex   结束下标
     * @return
     */
    private static int partition(int[] arr, int startIndex, int endIndex) {
        // 取第1个位置(也可以选择随机位置)的元素作为基准元素
        int pivot = arr[startIndex];
        int mark = startIndex;
        for (int i = startIndex + 1; i <= endIndex; i++) {
            if (arr[i] < pivot) {
                mark++;
                int p = arr[mark];
                arr[mark] = arr[i];
                arr[i] = p;
            }
        }
        arr[startIndex] = arr[mark];
        arr[mark] = pivot;
        return mark;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{4, 7, 3, 5, 6, 2, 8, 1};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
}


Tags:快速排序   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Go 语言实现快速排序算法
快速排序是由东尼&middot;霍尔所发明的一种排序算法,时间复杂度是 O(nlogn), 是不稳定排序算法。快速排序使用分治思想,通过一趟排序将要排序的数据分割成独立的两部分,其中一部...【详细内容】
2023-05-08  Search: 快速排序  点击:(357)  评论:(0)  加入收藏
数据结构与算法:快速排序
一、定义同冒泡排序一样,快速排序也属于交换排序,通过元素之间的比较和交换位置来达到排序的目的。不同的是,冒泡排序在每一轮中只把1个元素冒泡到数列的一端,而快速排序则在每...【详细内容】
2023-03-07  Search: 快速排序  点击:(116)  评论:(0)  加入收藏
高级排序算法之快速排序
前言今天继续算法学习,本次学习的是高级排序之快速排序。本文代码部分存在调用公共方法,可在文章:简单排序算法之冒泡、插入和选择排序-Java实现版 ,高级排序之归并排序、希尔排...【详细内容】
2022-08-08  Search: 快速排序  点击:(364)  评论:(0)  加入收藏
java快速排序
快速排序是一种非常高效的排序算法,它的实现,增大了记录和比较和移动的距离,从而减少总的比较此时和移动次数。采用分而治之的思想,将一个大的问题拆成一个小的问题,小的问题拆成...【详细内容】
2022-07-28  Search: 快速排序  点击:(247)  评论:(0)  加入收藏
你应该知道的常用排序算法之快速排序
人生有涯,学海无涯今天跟大家分享一个常用的排序算法&mdash;&mdash;快速排序。我想大家在日常的工作或者面试的时候肯定经常会遇到很多排序算法,而且快速排序算法往往是这里面...【详细内容】
2021-03-04  Search: 快速排序  点击:(390)  评论:(0)  加入收藏
计算机入门必备算法——快速排序法
1、引言今天的运气不是很好,再加上项目的压力。准备停止学习一周,等把项目这一关过了,再继续深入学习分享算法。后来吧今天遇到的事情都比较郁闷,也无心情继续开发项目。便想转...【详细内容】
2020-11-12  Search: 快速排序  点击:(404)  评论:(0)  加入收藏
图解快速排序:Go 实现
算法05:Golang快速排序Quick Sort1.什么是快速排序(Quick Sort)快速排序是由东尼&middot;霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要 &Omicron;(nlogn) 次比...【详细内容】
2020-10-12  Search: 快速排序  点击:(283)  评论:(0)  加入收藏
冒泡,选择,插入,希尔,归并,快速排序大合集,面试收藏必备
在很多大厂的面试中,算法是最基本的要求,像基础的算法,冒泡,选择,插入等,基本上都会问到。很多同学往往忽略了其重要程度,只注重编程语言,小编并不建议这样子,今天我们来梳理一下算法...【详细内容】
2020-05-03  Search: 快速排序  点击:(256)  评论:(0)  加入收藏
看完这个,你觉得你真的懂快速排序吗?
看似青铜实则王者很多人提起快排和二分都觉得很容易的样子,但是让现场Code很多就翻车了,就算可以写出个递归版本的代码,但是对其中的复杂度分析、边界条件的考虑、非递归改造、...【详细内容】
2019-11-27  Search: 快速排序  点击:(429)  评论:(0)  加入收藏
算法之常见排序算法-冒泡排序、归并排序、快速排序
冒泡排序时间之所以效率低,就是因为将所有数都一视同仁不做区分挨个比较,这是最普通的做事方法,所以效率也是最普通的,时间复杂度为N的平方;而归并排序效率高,则是采用了分治的思...【详细内容】
2019-10-22  Search: 快速排序  点击:(593)  评论:(0)  加入收藏
▌简易百科推荐
小红书、视频号、抖音流量算法解析,干货满满,值得一看!
咱们中国现在可不是一般的牛!网上的网友已经破了十个亿啦!到了这个互联网的新时代,谁有更多的人流量,谁就能赢得更多的掌声哦~抖音、小红书、、视频号,是很多品牌必争的流量洼地...【详细内容】
2024-02-23  二手车小胖说    Tags:流量算法   点击:(13)  评论:(0)  加入收藏
雪花算法详解与Java实现:分布式唯一ID生成原理
SnowFlake 算法,是 Twitter 开源的分布式 ID 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳...【详细内容】
2024-02-03   一安未来  微信公众号  Tags:雪花算法   点击:(50)  评论:(0)  加入收藏
程序开发中常用的十种算法,你用过几种?
当编写程序时,了解和使用不同的算法对解决问题至关重要。以下是C#中常用的10种算法,每个算法都伴随着示例代码和详细说明。1. 冒泡排序 (Bubble Sort):冒泡排序是一种简单的比...【详细内容】
2024-01-17  架构师老卢  今日头条  Tags:算法   点击:(44)  评论:(0)  加入收藏
百度推荐排序技术的思考与实践
本文将分享百度在推荐排序方面的思考与实践。在整个工业界的推广搜场景上,特征设计通常都是采用离散化的设计,需要保证两方面的效果,一方面是记忆,另一方面是泛化。特征都是通过...【详细内容】
2024-01-09  DataFunTalk  微信公众号  Tags:百度推荐   点击:(77)  评论:(0)  加入收藏
什么是布隆过滤器?如何实现布隆过滤器?
以下我们介绍了什么是布隆过滤器?它的使用场景和执行流程,以及在 Redis 中它的使用,那么问题来了,在日常开发中,也就是在 Java 开发中,我们又将如何操作布隆过滤器呢?布隆过滤器(Blo...【详细内容】
2024-01-05  Java中文社群  微信公众号  Tags:布隆过滤器   点击:(87)  评论:(0)  加入收藏
面向推荐系统的深度强化学习算法研究与应用
随着互联网的快速发展,推荐系统在各个领域中扮演着重要的角色。传统的推荐算法在面对大规模、复杂的数据时存在一定的局限性。为了解决这一问题,深度强化学习算法应运而生。本...【详细内容】
2024-01-04  数码小风向    Tags:算法   点击:(96)  评论:(0)  加入收藏
非负矩阵分解算法:从非负数据中提取主题、特征等信息
非负矩阵分解算法(Non-negativeMatrixFactorization,简称NMF)是一种常用的数据分析和特征提取方法,主要用于从非负数据中提取主题、特征等有意义的信息。本文将介绍非负矩阵分解...【详细内容】
2024-01-02  毛晓峰    Tags:算法   点击:(63)  评论:(0)  加入收藏
再谈前端算法,你这回明白了吗?
楔子 -- 青蛙跳台阶一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶,求该青蛙跳上一个n级的台阶总共需要多少种跳法。分析: 当n=1的时候,①只需要跳一次即可;只有一种跳法,即f(...【详细内容】
2023-12-28  前端爱好者  微信公众号  Tags:前端算法   点击:(108)  评论:(0)  加入收藏
三分钟学习二分查找
二分查找是一种在有序数组中查找元素的算法,通过不断将搜索区域分成两半来实现。你可能在日常生活中已经不知不觉地使用了大脑里的二分查找。最常见的例子是在字典中查找一个...【详细内容】
2023-12-22  小技术君  微信公众号  Tags:二分查找   点击:(78)  评论:(0)  加入收藏
强化学习算法在资源调度与优化中的应用
随着云计算和大数据技术的快速发展,资源调度与优化成为了现代计算系统中的重要问题。传统的资源调度算法往往基于静态规则或启发式方法,无法适应动态变化的环境和复杂的任务需...【详细内容】
2023-12-14  职场小达人欢晓    Tags:算法   点击:(165)  评论:(0)  加入收藏
站内最新
站内热门
站内头条