Java-快速排序

本文详细介绍了快速排序的基本原理和实现过程,包括选择基准元素、分区操作以及递归排序的步骤。通过示例代码展示了如何避免在遍历过程中出现死循环的问题,强调了在比较过程中不取等的重要性,确保正确交换元素位置。此外,还提供了快速排序的Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 原理以及实现说明

快速排序的原理其实很简单。

  • 首先有一串数组
    数组

  • 然后我们在数组内选一个数记为x,可以是第一个,最后一个,哪个都行,然后记录下来,就以取到最后一个元素为例吧。

  • (em,本来应该是随机取的,但是随机取的话,代码设计就有点麻烦,会碰到诸如角标越界,死循环之类的问题,这里就不做过多分析,有兴趣的小伙伴可以试试。)
    取到x

  • 然后呢,这个数组以x为界限分为前后两部分
    在这里插入图片描述

  • 然后对这前后两个部分的元素分别给指针进行遍历,注意一下遍历的方向,两个指针都往中间(也就是x)那边靠。
    在这里插入图片描述

  • 然后给个循环,让这两个部分每个元素同时与x进行大小比较,以从小到大排序为例的话,就是:

如果前面部分的遍历到的元素比x大,指针i就暂时停下来
后面部分如果遍历到比x小的,指针j也暂时停下来
然后比较两个指针的位置,
如果指针i在指针j的前面的话就交换两个指针指向的元素,然后两个指针继续刚才的比较操作
如果指针i在指针j的后面的话就停止整个遍历。

如此,就能保证在x左边的元素都比x小,在x的右边的元素都比x大。
然后不断递归上面的操作就行了。
附上代码如下:

package com.zero;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import static java.lang.System.exit;

public class QuickSort {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.valueOf(bufferedReader.readLine());
        String[] arr = bufferedReader.readLine().split(" ");
        if (n!=arr.length){
            System.out.println("输入错误");
            exit(0);
        }
        int[] arr2 = new int[n];
        for (int i = 0;i<n;i++){
            arr2[i] = Integer.valueOf(arr[i]);
        }

        fast_sort(arr2, 0, n-1);

        for (int i = 0;i<n;i++){
            System.out.print(arr2[i]+" ");
        }
    }

    private static void fast_sort(int[] arr2, int l, int r) {
        if (l>=r) return;           //注意这里要取等,如果不取等下面会死循环
        int x = arr2[r];
        int i = l-1;    //这里-1和下面+1的目的是防止数组中出现相同的值的情况导致下面出现死循环
        int j = r+1;
        while(i<j) {
            do { i++; } while (arr2[i] < x);//注意这里不能取到等,如果取等会越界
            do {j--;} while (arr2[j] > x);//注意这里不能取到等,如果取等会越界
            if (i<j)
                swap(arr2,i,j);
        }
        fast_sort(arr2,l,i-1);
        fast_sort(arr2,i,r);
    }

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

}


这里还是稍微解释一下为什么while那里不能取等,我相信有很多小可爱和我一样(猪头(~ ̄(OO) ̄)ブ保命),因为很常见的想法是指针指到的元素既然和x一样大就没有必要参与后面的交换了,索性让指针往后面走,可能会这么想。
但是实际上忽略了一种情况,这里还是直接上例子吧:

假设在i之前的元素全都是比x小的,此时指针i在x前面的一个位置找到了比x大的元素,这个时候i指针停了下来,
并且x后面的元素全部都是比x大的,这个时候j指针一路正常一路指到了x,然后让x和x比较,相等,(由于取等继续走)继续指,指到i,发现比x大,然后继续,指到了i前面的元素终于发现比x小的了,
然后比较i和j,发现j在i的前面,所以不交换位置,
这个时候我们注意到,无论循环递归多少次,这个在x前面的比x大的元素无论如何都换不到x的后面,所以会出现死循环。

简单的来说就是取等的目的是保证能够正常交换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值