图解:快速排序之单边循环法

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 单边循环法是快速排序的算法之一,之前的双边循环法从数列的两边交替遍历元素,虽然更加直观,不过代码实现起来相对复杂。而单边循环法就要简单多了,只需要从数组的一边对元素进行遍历和交换即可。

一、单边循环法概述

单边循环法是快速排序的算法之一,之前的双边循环法从数列的两边交替遍历元素,虽然更加直观,不过代码实现起来相对复杂。而单边循环法就要简单多了,只需要从数组的一边对元素进行遍历和交换即可。

二、逻辑推演

单边循环法的详细过程,假设数列为:[4,7,3,5,6,2,8,1]

image-20211104183334590

开始和双边循环法相似,首先选定基准元素。同时,设置一个mark指针记录数列的起始位置,该指针代表小于基准元素的区域边界。

image-20211104183450971

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

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

如果遍历到元素小于基准元素,则要做两件事:1.把mark指针右移1位,因为小于基准元素的区域边界增大了1;2.让最新遍历到的元素和mark指针所在位置的元素交换位置,因为最新遍历的元素归属于小于基准元素的区域。

先遍历元素到7,因为7>4所以继续向后遍历。

image-20211104183617085

然后遍历到元素3,3<4,所以mark指针右移1位。

image-20211104183726117

元素3和mark指针所在位置的元素交换,因为元素3属于小于基准元素的区域。

image-20211104183907169

如果按照这个思路继续遍历的话,图就如下所示了。

image-20211104184228947

省略中间的过程...最后把基准元素交换到mark指针所在位置,这一轮宣告结束,得到这样一个排列

image-20211104184445550

此时这一轮排序宣告结束,继续下一轮排序。

这个方法只需要单边循环,确实简单了许多,下面我们用代码来实现

三、代码实现

    public static void main(String[] args) {
   
   
        int[] arr = new int[]{
   
   4,3,7,5,6,2,8,1};
        quickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    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);
    }
    //单边循环分治
    private static int partition(int[] arr, int startIndex, int endIndex) {
   
   
        //获取第一个位置,成为基准元素
        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;
    }

总结

以递归为基础的单边循环法成功实现排序,其实除了递归实现以外,我们还可以使用非递归的实现方式完成快速排序,非递归的方式在下一篇文章。

目录
相关文章
|
7月前
|
API
代码随想录 Day10 栈与队列 LeetCode T239 滑动窗口的最大值 T347 前K个高频元素
代码随想录 Day10 栈与队列 LeetCode T239 滑动窗口的最大值 T347 前K个高频元素
30 0
|
7月前
|
人工智能 算法
【算法分析与设计】递归与分治策略(二)
【算法分析与设计】递归与分治策略
|
1月前
|
搜索推荐 算法 索引
【排序算法】深入解析快速排序(霍尔法&&三指针法&&挖坑法&&优化随机选key&&中位数法&&小区间法&&非递归版本)
【排序算法】深入解析快速排序(霍尔法&&三指针法&&挖坑法&&优化随机选key&&中位数法&&小区间法&&非递归版本)
|
7月前
|
机器学习/深度学习 算法 编译器
【算法分析与设计】递归与分治策略(一)
【算法分析与设计】递归与分治策略
|
10月前
|
搜索推荐
图解:快速排序算法之双边循环法
之前我们学习了冒泡排序,有没有比冒泡排序更快的排序算法呢?当然有,例如快速排序,归并排序,堆排序。接下来即将介绍的快速排序就是由冒泡排序演变而来的。
122 0
图解:快速排序算法之双边循环法
|
5月前
|
Java C++ Python
分治策略之最大子数组(Python实现)
分治策略之最大子数组(Python实现)
38 0
|
5月前
|
搜索推荐 算法
手撕排序算法3:优化版冒泡排序和快速排序的三种方法(包括三数取中,小区间优化,递归版本)(下)
手撕排序算法3:优化版冒泡排序和快速排序的三种方法(包括三数取中,小区间优化,递归版本)(下)
|
5月前
|
搜索推荐 算法 C语言
手撕排序算法3:优化版冒泡排序和快速排序的三种方法(包括三数取中,小区间优化,递归版本)(上)
手撕排序算法3:优化版冒泡排序和快速排序的三种方法(包括三数取中,小区间优化,递归版本)(上)
手撕排序算法3:优化版冒泡排序和快速排序的三种方法(包括三数取中,小区间优化,递归版本)(上)
|
7月前
|
算法
算法:分治思想处理快排递归以及快速选择/最小K个数问题
算法:分治思想处理快排递归以及快速选择/最小K个数问题
|
7月前
|
算法 搜索推荐 Windows
【算法分析与设计】递归与分治策略(三)
【算法分析与设计】递归与分治策略