快排算法

快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。
它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

简而言之,快排算法,就是我们常说的二分法。 通过基准值,将数字序列 分为 小于临界值的部分,和大于临界值的部分。然后在每一部分继续递归执行分割,直至 原始序列变成有序序列。

关键:

  1. 基准值是一个序列中随机的一个值,在整个排序过程中,是确定不变的。
  2. 这种类似于细胞分裂的排序方式,明显是一种递归的思想。因此算法大的骨架,可以采用递归方法,或者栈的回溯来实现。
实现
递归方法实现:
/** 递归方法实现:
*@param data 数据源
*@param startIndex 开始处理的下标 *@param
*/
public static void  recursiveSort(int[] data,int startIndex,int endIndex){
   if(startIndex<endIndex){
      //获取基准元素的位置
      int privotIndex= partition(data, startIndex,endIndex);
      //根据基准元素的位置,分成两部分序列,继续进行排序
       //左半部分
       recursiveSort(data,startIndex,privotIndex-1);
        //右半部分
       recursiveSort(data,privotIndex+1,endIndex);
   }

}
用栈实现:
/** 递归方法实现:
*@param data 数据源
*@param startIndex 开始处理的下标 *@param
*/
public static void recursiveSortStatck(int[] data, int startIndex, int endIndex) {

        Stack<Map<String, Integer>> stack = new Stack<>();

        Map<String, Integer> pair = new HashMap<>();
        pair.put("startIndex", startIndex);
        pair.put("endIndex", endIndex);
        stack.push(pair);

        while (!stack.isEmpty()) {

            Map<String, Integer> pop = stack.pop();
            Integer popStart = pop.get("startIndex");
            Integer popEnd = pop.get("endIndex");


            //获取基准元素的位置
            int privotIndex = partition(data, popStart, popEnd);

            if (privotIndex - 1 > popStart) {
                Map<String, Integer> startMap = new HashMap<>();
                startMap.put("startIndex", popStart);
                startMap.put("endIndex", privotIndex - 1);
                stack.push(startMap);
            }


            if (privotIndex + 1 < popEnd) {
                Map<String, Integer> endMap = new HashMap<>();
                endMap.put("startIndex", privotIndex + 1);
                endMap.put("endIndex", popEnd);
                stack.push(endMap);
            }


        }

    }

很简单,以上代码已经写出了算法的骨架,现在问题的关键又 转换到 获取基准元素的位置 partition 方法中,因此该方法的目的。

  1. 使data 数组 ,在 【startIndex,endIndex】在区间内是有序的。
  2. 在该区间内,返回基准元素的位置。
双边循环法
 /**
     * 双边循环
     * @param datas
     * @param startIndex
     * @param endIndex
     * @return
     */
    public static int partition (int[] datas,int startIndex,int endIndex){
       //取一个基准值(取第一个)
       int standard=datas[startIndex];
       //起始位置的游标A
       int startCursor=startIndex;
       //结束位置的游标B
       int endCursor=endIndex;

       //当两个游标不重合的时候
       while (startCursor!=endCursor){
           //从右往左比较,当B 游标对应的值 不小于temp时(该值在temp的右边,),B游标向左移动一位,比较上一位的值
           while (datas[endCursor]>=standard&&endCursor>startCursor){
               endCursor--;
           }
           //当从右向左比较时,发现值 C 小于temp 时(该值应该在temp的左边),暂停。开始从左往右遍历
           //当A 游标对应的值不大于temp 的时候(该值在temp的左边),A游标向有移动一位,比较下一位值
           while (datas[startCursor]<=standard&&startCursor<endCursor){
               startCursor++;
           }
           //当从左往右比较,遇到比temp 大的值 D(该值应该在temp的右边)时候停止移动。

           //综上,可知,c 应该应该在基准值的左侧,d  应该在基准值的右侧 ,所以交换 C 与 D 的值,
           if(startCursor!=endCursor){
               int temp=datas[endCursor];
               datas[endCursor]=datas[startCursor];
               datas[startCursor]=temp;
           }

       }
        //当 游标 A,B 重合的时候,此时应该是基准值的准确位置, 交换 standard 和 重合位置的值
         int tempB=datas[endCursor];
         datas[endCursor]=standard;
         datas[startIndex]=tempB;
        return  endCursor;

    }
单 边循环法
/**
     * 单边循环
     * @param datas
     * @param startIndex
     * @param endIndex
     * @return
     */
  public static int findCenterNumB(int[] datas,int startIndex,int endIndex){
        int standard=datas[startIndex];
        //用来标记小于基准元素的边界
        int currentCursor=startIndex;
        for (int i= startIndex;i<=endIndex;i++){
            int data = datas[i];
            //当元素小于基准值的话,
            if(data<standard){
            // 小于基准边界+1
                currentCursor++;
                //交换游标位置 和遍历到位置的数据
                int temp=datas[currentCursor]
                datas[currentCursor]=datas[i];
                datas[i]=temp;
            }
        }
        //将基准元素交换到游标的位置上。
     
         datas[startIndex]= datas[currentCursor];
         datas[currentCursor]=standard;
        return currentCursor;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值