快速排序非递归版 Java实现

import org.junit.Test;

import java.util.Arrays;
import java.util.LinkedList;

public class Sort {

    private static class Range{
        int begin, end;
        Range(int b, int e){
            begin = b;
            end = e;
        }
    }

    public static <T extends Comparable> void fastSort(T[] array){
        // 在这里,不使用系统栈(递归),但其实还是得用栈来完成
        LinkedList<Range> stack = new LinkedList<>();
        // 分治法开始会产生两个子问题,然后子问题二分四产生子子问题然后四分八,八分十六...
        // 直到分成的子问题可以立即被解出,此时就获得了总问题的解
        // 快排的层层递归中实际上变化的也只是数组的起始与结束坐标而已
        // 此处使用一个Range对象来维护这两个参数
        stack.add(new Range(0, array.length - 1));

        // 开始模拟递归
        while(!stack.isEmpty()){
            // 取出栈顶元素做一次快排
            Range r = stack.pop();
            // 重载函数fastSort(见下方)会返回单次排序后的中心坐标
            int mi = fastSort(array, r.begin, r.end);
            // 若为-1说明这个子数组已经不能再一分为二了,跳过即可
            if(mi == -1){
                continue;
            }
            // 以中心坐标mi为中点分割成左右两个子数组压栈(递归)
            stack.add(new Range(r.begin, mi - 1));
            stack.add(new Range(mi + 1, r.end));
        }
    }

    private static <T extends Comparable> int fastSort(T[] array, int bIndex, int eIndex){
        // 单次快排实现
        if(eIndex - bIndex < 1){
            return -1;
        }
        int l = bIndex, r = eIndex;
        // 利用一个标志变量控制向左走还是向右走
        boolean right = true;
        // 获取基准值,这里是以给定数组的 起始下标 上的元素
        T c = array[bIndex];
        while(l < r){
            if(right){
                // 从右向左查找一个比基准值小的
                if(array[r].compareTo(c) < 0){
                    // 找到之后翻置标志变量,换方向
                    right = false;
                    continue;
                }
                --r;
            }else{
                // 先加一次,跳过基准值本身
                ++l;
                // 从左向右查找一个比基准值大的
                if(array[l].compareTo(c) > 0){
                    // 同理,翻置
                    right = true;
                    // 交换两个满足条件的元素
                    swap(array, l, r);
                    // 这个时候记得把r下标向左移一位(不移也行,但会多一次重复判断)
                    --r;
                }
            }
        }
        // 最后把基准值交换到中心坐标
        swap(array, bIndex, l);
        // 若是递归代码就很简单,就这么两行,不难看出在递归过程中变化的就是起始与结束坐标
//        fastSort(array, bIndex, l - 1);
//        fastSort(array, l + 1, eIndex);
        return l;
    }

    private static void swap(Object[] arr, int index0, int index1){
        Object temp = arr[index0];
        arr[index0] = arr[index1];
        arr[index1] = temp;
    }


    @Test
    public void testFastSort(){
        Integer[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8, 85, 100,434, 5, 66, 42, 22, 90};
        fastSort(arr);
        System.out.println(Arrays.toString(arr));

        Integer[] arr2 = {8, 3, 10, 9, 9, 4, 6, 6, 7, 9, 3};
        fastSort(arr2);
        System.out.println(Arrays.toString(arr2));
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值