递归实现快速排序

方法一:

public class QuickSort {
    public static void main(String[] args) {
        RecursionDemo rs = new RecursionDemo();
        int[] arr = {6,1,2,7,9,3,4,5,10,8};
        System.out.println("排序前");
        System.out.println(Arrays.toString(arr));
        rs.quickSort(arr,0,arr.length-1);
        System.out.println("排序后");
        System.out.println(Arrays.toString(arr));
    }
    /**
     * 快速排序
     * 分而治之思想
     *
     * 1 选择一个基准数,然后将比基准数小的放在基准数的左边,大的放在基准数的右边
     * 2 选择数列的第一个数作为基准数
     * 3 两个指针,分别指向数列的头和尾
     * 4 尾指针依次往前移动,当尾指针指向的元素比基准数小时,停下来,头指针开始依次往后移动,当头指针指向的元素比基准数大,停下来,将此时头尾指针指向的元素交换位置
     * 5 重复4的过程 直到头尾相遇
     * 6 将头尾指针指向的元素和基准数交换顺序
     */
    public void quickSort(int[] arr,int left,int right){
        if(left<=right){  //到最后左边第一个位置一个数的情况,start=end=0时,end-1=-1报错
            //定义基准数
            int base = arr[left];
            //两个指针,分别指向数列的头和尾
            int start = left;
            int end = right;
            // 4-5循环的过程
            while(start<end){
                //尾指针依次往前移动,当尾指针指向的元素比基准数小时,停下来
                while(start<end&&arr[end]>=base){
                    end--;
                }
                //头指针开始依次往后移动,当头指针指向的元素比基准数大,停下来
                while(start<end&&arr[start]<=base){
                    start++;
                }
                swap(arr,start,end);
            }
            //循环结束 start和end相遇
            //6 将头尾指针指向的元素和基准数交换顺序
            swap(arr,left,end);
            //递推等价表达式
            //基准数左边的数列排序
            quickSort(arr,left,end-1);
            //基准数右边的数列排序
            quickSort(arr,end+1,right);
        }

    }
    private void swap(int[] arr, int start, int end) {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
    }
}

方法二:

import java.util.Arrays;
/*
这段代码实现了快速排序算法。下面是对代码的解释:
quickSort 方法接受一个整型数组 arr,以及数组的低位索引 low 和高位索引 high。它返回一个经过排序的整型数组。
首先,通过判断 low 是否小于等于 high 确定是否需要进行排序。如果 low 大于 high,则表示已经完成排序,不需要再进行操作。
创建两个指针 i 和 j,分别指向数组的低位和高位。
将数组的第一个元素 arr[low] 作为基准数 key。
进入循环,当 i 小于 j 时,执行以下操作:
从右侧开始,逐个将指针 j 向左移动,直到找到一个小于基准数 key 的元素 arr[j]。
如果 i 小于 j,则将 arr[j] 赋值给 arr[i],并将 i 自增1。
从左侧开始,逐个将指针 i 向右移动,直到找到一个大于等于基准数 key 的元素 arr[i]。
如果 i 小于 j,则将 arr[i] 赋值给 arr[j],并将 j 自减1。
重复步骤5,直到 i 不小于 j,此时将基准数 key 放置在正确的位置上(arr[i] = key)。
接下来,对基准数左侧的子数组(low 到 i-1)和右侧的子数组(i+1 到 high)进行递归调用 quickSort 方法,分别进行排序。
最后,返回经过排序的整型数组 arr。
通过不断地将基准数放置在正确的位置上,并对左右子数组进行递归排序,最终实现了快速排序算法。
*/

/*
 arr[i++] = arr[j];这样赋值不回将原有的i处的值覆盖吗
 在这段代码中,arr[i++] = arr[j] 的作用是将右侧找到的小于基准数的元素 arr[j] 赋值给左侧指针 i 所指向的元素,并将 i 自增1。
由于后置自增运算符 ++ 的优先级比赋值运算符 = 高,所以 i++ 先执行,等价于以下两步操作:
将 arr[j] 赋值给 arr[i]。
将 i 自增1。
因此,每次执行 arr[i++] = arr[j] 时,都会将右侧找到的小于基准数的元素赋值给左侧指针所指向的元素,并将左侧指针向右移动一位。
这种方式不会覆盖原来的 i 处的值,因为在执行该语句时,i 已经自增1了,所以新赋值的元素会放在 i 所指向的下一个位置上。
*/

/*找到需要交换的元素,将需要交换的元素与基准值交换*/
public class QuickSort2 {
    public static void main(String[] args) {
        int[] arr={-34,200,32,1,4,7,100};
        System.out.println(Arrays.toString(quickSort(arr,0,arr.length-1)));
    }
    public static int[] quickSort(int[] arr,int low,int high){
        if(low<=high){//不加这个条件会死循环,左指针小于右指针执行(<或<=都可)
            int i=low;//左指针
            int j=high;//右指针
            int key=arr[low];//第一个数作为基准数
            while(i<j){
                while(i<j&&arr[j]>=key)//先右侧
                {
                    j--;
                }
                if(i<j) {
                    arr[i++] = arr[j];
                }//先赋值在自增
                while(i<j&&arr[i]<key) {
                    i++;
                }
                if(i<j) {
                    arr[j--] = arr[i];
                }//先赋值再自减
            }
            arr[i]=key;
            quickSort(arr,low,i-1);//给左边排序
            quickSort(arr,i+1,high);//给右边排序
        }
        return arr;
    }
}

方法三:

/*找两个需要交换的数,将它们的位置进行交换*/
public class QuickSort {
    //快速排序
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {//左指针<右指针条件满足执行
            int pivotIndex = partition(arr, low, high);//每次排序后基准数所在的位置
            //arr 是待排序的数组,low 是子数组的起始索引,pivotIndex - 1 是基准元素左侧子数组的结束索引。

            quickSort(arr, low, pivotIndex - 1);//左边的子数组,将基准元素左侧的所有元素进行排序,使得它们小于或等于基准元素
            //arr 是待排序的数组,pivotIndex + 1 是基准元素右侧子数组的起始索引, high 是子数组的结束索引。
            quickSort(arr, pivotIndex + 1, high);//右边的子数组,将基准元素右侧的所有元素进行排序,使得它们大于或等于基准元素
        }
    }
    public static int partition(int[] arr, int low, int high) {
        int pivot = arr[low];//基准数
        int left = low + 1;//左指针
        int right = high;//右指针
        // while():交换一轮
        while (true) {
            //判断左(left)指针
            while (left <= right && arr[left] <= pivot) {//如果左边的数小于基准数,则指针++
                left++;
            }
            //判断右(right)指针
            while (left <= right && arr[right] >= pivot) {//如果右边的数大于基准数,则指针--
                right--;
            }
            //left和right分别找到需要交换的数,将这两个数交换位置
            if (left <= right) { //将基准元素左侧的元素中的一个较大元素与基准元素右侧的元素中的一个较小元素交换位置,以确保左侧的元素都比基准元素小,右侧的元素都比基准元素大。
                int temp = arr[left];
                arr[left] = arr[right];
                arr[right] = temp;
            } else {
                break;
            }
        }
        //将基准数放在合适的位置
        int temp = arr[low];//temp是基准数
        arr[low] = arr[right];//右侧子数组中的元素(right 索引位置的元素)赋值给 low 索引位置。现在,原先的基准数被移到了右侧子数组的位置,因为右侧的元素应该大于或等于基准数。
        arr[right] = temp;//将之前存储在 temp 中的基准数的值赋给 right 索引位置。现在,基准数被移回了它最终的位置,它的左侧元素都小于或等于它,右侧元素都大于或等于它
        return right;//基准数排序后在数组中的位置
    }

    public static void main(String[] args) {
        int[] arr = {7, 2, 1, 6, 8, 5, 3, 4};
        int n = arr.length;
        quickSort(arr, 0, n - 1);
        System.out.println("快速排序结果:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值