非递归快速排序

快速排序常常使用递归算法来实现,其运行时只使用lgN 的系统调用栈。如果想更清楚快速排序的运行过程,我们可以使用非递归的方法来实现快速排序。其方法最重要的部分是显式的使用一个栈来保存切分数组的下标,使用一个循环将出栈的子数组切分为二,并将结果重新入栈(这两个切分结果的入栈顺序不影响最后结果),直到结果都成为长度为一的子数组,此时排序完毕。
代码如下:

// 非递归快速排序
public class Quick4 {
    public static <T> void sort(Comparable<T>[] a) {
        if (a == null) {
            return;
        }
        // 存放切分后的子数组在原数组的下标,而不是存放子数组元素
        Stack<Integer> stack = new Stack<>();
        int lo = 0, j, hi = a.length-1;// 初始数组即为原始数组
        stack.push(hi);// 尾先入栈
        stack.push(lo);// 头后入栈
        while (!stack.isEmpty()) {
            lo = stack.pop();// 头先出栈
            hi = stack.pop();// 尾后出栈
            j = partition(a, lo, hi);// 将子数组切分
            // 如果切分后的子数组长度为1则其排序完成,不再入栈
            if (j - 1 > lo) {// 左子数组
                stack.push(j - 1);
                stack.push(lo);
            }
            if (j + 1 < hi) {// 右子数组
                stack.push(hi);
                stack.push(j + 1);
            }
        }
    }

    public static <T> int partition(Comparable<T>[] a, int lo, int hi) {
        int i = lo, j = hi + 1;
        Comparable<T> v = a[lo];// 切分元素选为首元素
        while (true) {
            while (less(a[++i], v)) {// 向右扫描
                if (i == hi) {
                    break;
                }
            }
            while (less(v, a[--j])) {// 向左扫描
                if (j == lo) {
                    break;
                }
            }
            if (i >= j) {// 指针相遇,切分位置确定
                break;
            }
            exch(a, i, j);// 交换左右逆序元素
        }
        exch(a, lo, j);// 将切分元素放在切分位置
        return j;
    }

    @SuppressWarnings("unchecked")
    public static <T> boolean less(Comparable<T> v, Comparable<T> w) {
        return v.compareTo((T) w) < 0;
    }

    private static <T> void exch(Comparable<T>[] a, int i, int j) {
        Comparable<T> t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

    public static void main(String[] args) {
        String[] a = "qwertyuiopasdfghjklzxcvbnm".split("");
        sort(a);
        for (String string : a) {
            System.out.print(string + " ");
        }
    }
}

在非递归的快速排序算法中,一个很重要的技巧就是循环的将出栈(出队)的元素处理,再把结果重新入栈(入队),直到满足一定条件元素不再入栈(入队),循环的条件是栈(队列)非空。这个技巧在以上代码中的体现为:

Created with Raphaël 2.1.0 初始数组入栈 子数组出栈 并切分为二 结果数组长 度大于1? 结果数组 重新入栈 数组排序完成 yes no
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值