快速排序

快速排序

快速排序是使用分治的思想,先找出基准,以该基准进行二分分治递归

递归首先要找出递归出口,那何处为递归出口呢,questSort方法是递归体,当其left与right相遇则说明整个数组已遍历完成,可以退出循环

  • 双向指针

    指的是使用两个不同方向的指针

    思路:(保证数组左边的数一直比基准小,数组右边的值一直比基准大)

    步骤:1,从右边一直遍历,直到找到比基准小的值,停留在该下标(为什么需要从右边开始? 看代码注释)

    ​ 2,从右边第2个数字开始遍历,一直到找到比基准大的下标

    ​ 3,交互左右指针的下标所存的内容,然后继续上面的方法,一直到左右两个指针相遇

    ​ 4,左右两个指针相遇时,将左边的指针的值与基准交换,返回左边的指针的下标,这个为基准值

    常规做法是使用双向指针去完成,但是注意需要先从右开始遍历,再从做遍历,

       public static void questSort(int[] a, int left , int right){
                //递归结束条件
                if(left>=right){
                    return ;
                }
                //找到基准
                int patten = patten(a, left, right);
                //左边排序
                questSort(a,left,patten-1);
    
              //有有右边排序
                questSort(a,patten+1,right);
    
            }
    
    
            //分治,双向循环
            // 找出基准的下标
            public static int patten(int[] a, int start ,int end) {
                //双向指针
                int left = start;
                int right = end;
                int temp = a[start]; //这里默认使用数组开头的第一个数做为基准
    
                while (left != right) {
                 //必须右边针先移,为什么???因为如果没有先控制右边的过来,会导致,交换的值
                   //left 跳到大的一部分,导致排序有误差
                   //为什么要小于或者等于,控制指针左移动
                    while (a[right] > temp && left < right) {
                        right--;
                    }
    
                     //控制left指针,右移,a[left] 必须<=,不然出现有与temp一样的值会出现死循环,必须         索引值都
                    //扫描到
                    while (a[left] <= temp && left < right) {
                        left++;
                    }
    
                    if (left < right) {
                        int temp2 = a[right];
                        a[right] = a[left]; 
                        a[left] = temp2;
                    }
                }
                //pivot 和指针重合点交换
               // int pivote = a[left];
                a[start] = a[left];
                a[left] = temp;
                return left;
            }
    
    
  • 单向指针

    指的是使用两个相同方向的指针

    思路:设置一个mark指针,mark一开始指向第一个元素(即基准元素) ,然后设置另一个指针(i)循环向右移动,当i遇到比基准小的值则停下来,则mark的指针向下移一位,并与i所在的位置交换值,保证mark指针左边以及其指向的值都是小于或是等于基准元素的。最后将mark的值与基准交换,返回基准值的位置mark

       //单向循环,前后指针法
    
            public static void questSort2(int[] a,int left ,int right){
               //递归结束条件
                if(left >= right){
                    return;
                }
    
                  //找出基准元素
                int provid = patten2(a, left, right);
                System.out.println(provid);
    
                  //分治
                questSort2(a,left,provid-1);
    
                questSort2(a,provid+1,right);
    
    
    
            }
    
             //单向,前后指针
            public static int patten2(int[] a , int start , int end){
                  // System.out.println(Arrays.toString(a));
                int left = start+1;
                int right = end;
                int temp = a[start];//第一个
               //mark向左是小于temp的值
                int mark = start;
                
                
                while(left<=right){
                 //找到temp小的值
                    if(a[left]<=temp){
                        mark++;
                         //交换
                        int k = a[left];
                        a[left] = a[mark];
                        a[mark] = k;
    
                    }
                    left++;
                }
    
                a[start] = a[mark];
                a[mark] = temp;
                return mark;
            }
    
    
  • 挖坑法

    挖坑法实际上与双向指针类似,只是先把第一个数暂时存起来,然后从右边开始找一个小于基准数去填左边那个小的数,接着右边的那个数就为空了(假设填补后,就为空),那现在就从做找一个大于基准的数来填这个空,但左右两个指针相遇,则结束


        //快排,挖坑
        public static void questSort5(int[] a, int left ,int right){
           //递归结束
            if(left>=right){
                return ;
            }

            int patten5 = patten5(a, left, right);

            questSort5(a,left,patten5-1);

            questSort5(a,patten5+1,right);


        }

        //挖坑法
        private static int patten5(int[] a, int left, int right) {

            int i = left;
            int j = right;
            int temp = a[left];

            while(i!=j){
                while(a[j] >= temp && i<j){
                 //j 找小
                    j--;
                }
                a[i] = a[j];

                while(a[i]< temp && i<j){
                 //找大
                    i++;
                }
                a[j] = a[i];
            }

            a[i] = temp;
            return i;
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值