快速排序详细解说

思路解析

1)取最右侧的值为基准值base,从数组的左右两边分别开始查找,先从左往右找比基准值大的值,再从右往左找比基准值小的数,找到之后,将两个找到的数进行交换
在这里插入图片描述
2)在继续刚才的步骤,继续进行交换
在这里插入图片描述
3)直到left和right重合,就把重合的位置与基准值base交换
在这里插入图片描述
4)交换之后,原理的base就到了之前的重合位置,然后以这个数为分界线,分成左右两边,并对着两边的数组分别进行上述操作(递归)
在这里插入图片描述

代码示例

1)递归实现

 public static void quickSort(int[] array){
        //辅助完成递归过程
        quickSortHelper(array,0,array.length-1);
    }

    private static void quickSortHelper(int[] array, int left, int right) {
        if (left >= right){
            //区间中又0个元素或者1个元素,此时不需要排序
            return;
        }
        int index = partition(array,left,right);//left和right的重合位置
        quickSortHelper(array,left,index-1);
        quickSortHelper(array,index + 1,right);
    }

    private static int partition(int[] array, int left, int right) {
        int i = left;
        int j = right;

        //取最右侧元素为基准值
        int base = array[right];
        while (i < j){

            //从左往右找到比基准值大的元素
            while (i < j && array[i] <= base){
                i++;
            }
            //当上面的循环结束时,i要么和j重合,要么i就指向一个大于base的值

            //从右往左找比基准值小的元素
            while (i < j && array[j] >= base){
                j--;
            }
            //当上面的循环结束时,i要么和j重合,要么j就指向一个小于base的值

            //交换i和j的位置
            exchange(array,i,j);
        }
        //当i和j重合的时候,最后一步,要把重合位置的元素和基准值进行交换
        exchange(array,i,right);
        return i;
    }

2)非递归实现(也与上述的思路分析一致)

public static void quickSortByLoop(int[] array){
        //借助栈,模拟实现递归的过程
        //stack用来存放数组下标,通过下标来表示接下来要处理的区间是啥
        Stack<Integer> stack = new Stack<>();
        //初始情况下,先把右侧边界下标入栈,再把左侧边界入栈,左右边界仍然构成前闭后闭区间
        stack.push(array.length-1);//右侧
        stack.push(0);//左侧

        while (!stack.isEmpty()){
            int left = stack.pop();
            int right = stack.pop();
            if (left >= right){
                //区间中只有0个或1个元素,不需要整理
                continue;
            }

            //通过partition把区间整理成以基准值为中心,左侧小于等于基准值,右侧大于等于基准值的形式
            int index = partition(array,left,right);

            //准备一下区间
            //[index=1,right]基准值右侧区间
            stack.push(right);
            stack.push(index+1);

            //[left,index+1]基准值左侧区间
            stack.push(index - 1);
            stack.push(left);
        }
    }

性能分析

时间复杂度:
最好:O(n * log(n))
平均:O(n * log(n))
最坏:O(n^2)

空间复杂度:
最好:O(log(n))
平均:O(log(n))
最坏:O(n)

稳定性:
不稳定排序

注意事项

1)如果是是先从左往右找,再从右往左找,left和right重合位置的元素一定大于等于基准值;
如果是是先从右往左找,再从左往右找,left和right重合位置的元素一定小于等于基准值。

2)效率和基准值的好坏相关:基准值的是一个接近数组中位数的元素,划分出来的左右区间比较均衡,此时效率就比较高,如果当前取到的基准值是最大值或者最小值,此时的划分就不均匀,效率就低。

优化分析

1.优化基准值的取法:三个元素取中(最左侧元素,中间未知元素,最右侧元素)取中间基准值,把确认的基准值交换到数组末尾或者开始,为了后面整理动作做铺垫

2.当区间已经比较小的时候,再去递归其实效率已经不高了,不再继续递归,而是直接进行插入排序

3.如果区间特别大,递归深度也会非常深,当递归深度到达一定程度的时候,把当前区间的排序使用堆排序来进行优化

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Activity 是 Android 应用程序的基本组成部分之一,它负责展示用户界面和处理与用户的交互。Activity 可以看作是一个具有生命周期的窗口,它可以接收来自系统或用户的事件并作出响应。 Activity 的主要作用是管理用户界面和应用程序状态,它可以通过 setContentView() 方法加载布局文件并显示用户界面,同时也可以实现用户与应用程序之间的通信和数据交互。例如,当用户点击按钮或输入文本时,Activity 可以响应这些事件并执行相应的操作。 Activity 还可以通过 Intent 启动其他 Activity,实现多个界面的切换和交互。在启动另一个 Activity 时,当前 Activity 可以传递一些数据给被启动的 Activity,也可以接收被启动的 Activity 返回的数据。 Activity 生命周期包括以下几个阶段: 1. onCreate():在 Activity 创建时被调用,用于初始化界面和数据。 2. onStart():在 Activity 可见但没有获取焦点时被调用,用于执行一些初始化操作。 3. onResume():在 Activity 可见并获取焦点时被调用,用于开始执行程序逻辑。 4. onPause():在 Activity 失去焦点但仍可见时被调用,用于释放资源和保存数据。 5. onStop():在 Activity 不再可见时被调用,用于释放资源和保存数据。 6. onDestroy():在 Activity 被销毁时被调用,用于释放资源和清理数据。 Activity 生命周期中的每个阶段都提供了一些回调方法,可以在这些方法中执行一些操作,例如初始化界面、加载数据、保存状态等。 总的来说,Activity 是 Android 应用程序的基本组成部分之一,它负责展示用户界面和处理与用户的交互,通过生命周期管理应用程序状态,实现多个界面的切换和交互。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值