vlambda博客
学习文章列表

面试官: 不用递归就不会快速排序了? -_-||: 瞧不起谁呢

面试官: 非递归的方式写一下快速排序?

-_-||: 额...

面试官: 就这?

-_-||: ...

 非递归实现快排思路 

代码中一层一层的方法调用, 本身就使用了一个方法调用栈. 每次进入一个新方法, 相当于入栈, 每次有方法返回, 相当于出栈.

所以, 可以把原本递归实现转化成一个栈的实现, 在栈中存储每次方法调用的参数.



 quickSort的非递归部分实现 

面试官: 不用递归就不会快速排序了? -_-||: 瞧不起谁呢

非递归实现快排: 在单边循环法基础上演变, 不同的是quickSort().

public static void quickSort(int[] arr, int startIndex, int endIndex) {
    // 用一个集合栈来代替递归的函数栈
    Stack<Map<String, Integer>> quickSortStack = new Stack<Map<String, Integer>>();

    // 数组的下标通过哈希的形式入栈
    Map indexParam = new HashMap();
    indexParam.put("startIndex", startIndex);
    indexParam.put("endIndex", endIndex);
    quickSortStack.push(indexParam);

    // 循环结束条件:栈为空
    while (!quickSortStack.isEmpty()) {
        // 栈顶元素出栈,得到起止下标
        Map<String, Integer> param = quickSortStack.pop();
        // 得到基准元素位置
        int standardIndex = partition2(arr, param.get("startIndex"), param.get("endIndex"));
        // 根据基准元素分成两部分, 把每一部分的起止下标入栈
        if (param.get("startIndex") < standardIndex - 1) {
            Map<String, Integer> leftParam = new HashMap<>();
            leftParam.put("startIndex", param.get("startIndex"));
            leftParam.put("endIndex", param.get("endIndex"));
            quickSortStack.push(leftParam);
        }
        if (param.get("endIndex") > standardIndex + 1) {
            HashMap<String, Integer> rightParam = new HashMap<>();
            rightParam.put("startIndex", standardIndex + 1);
            rightParam.put("endIndex", param.get("endIndex"));
            quickSortStack.push(rightParam);
        }

    }

}


 非递归快排的完整实现 

面试官: 不用递归就不会快速排序了? -_-||: 瞧不起谁呢

/**
 * @description: 非递归实现快速排序
 * @author: liangyadong
 * @date: 2021/7/12 0012 21:08
 **/

public class QuickSortNonRecur {

    public static void quickSort(int[] arr, int startIndex, int endIndex) {
        // 用一个集合栈来代替递归的函数栈
        Stack<Map<String, Integer>> quickSortStack = new Stack<Map<String, Integer>>();

        // 数组的下标通过哈希的形式入栈
        Map indexParam = new HashMap();
        indexParam.put("startIndex", startIndex);
        indexParam.put("endIndex", endIndex);
        quickSortStack.push(indexParam);

        // 循环结束条件:栈为空
        while (!quickSortStack.isEmpty()) {
            // 栈顶元素出栈,得到起止下标
            Map<String, Integer> param = quickSortStack.pop();
            // 得到基准元素位置
            int standardIndex = partition(arr, param.get("startIndex"), param.get("endIndex"));
            // 根据基准元素分成两部分, 把每一部分的起止下标入栈
            if (param.get("startIndex") < standardIndex - 1) {
                Map<String, Integer> leftParam = new HashMap<>();
                leftParam.put("startIndex", param.get("startIndex"));
                leftParam.put("endIndex", param.get("endIndex"));
                quickSortStack.push(leftParam);
            }
            if (param.get("endIndex") > standardIndex + 1) {
                HashMap<String, Integer> rightParam = new HashMap<>();
                rightParam.put("startIndex", standardIndex + 1);
                rightParam.put("endIndex", param.get("endIndex"));
                quickSortStack.push(rightParam);
            }

        }

    }

    /**
     * 分治(单边循环法)
     *
     * @param arr        待交换的数组
     * @param startIndex 起始下标
     * @param endIndex   结束下标
     * @return 基准元素的位置
     */

    private static int partition(int[] arr, int startIndex, int endIndex) {
        // 取第一位元素作为基准元素
        int standardValue = arr[startIndex];
        // 指针指向数列的起始位置,mark代表小于基准元素的区域边界
        int mark = startIndex;

        // 遍历数组,如果遍历到的元素小于基准元素: 1. 2.
        for (int i = startIndex + 1; i <= endIndex; i++) {
            if (arr[i] < standardValue) {
                // 1.指针右移一位
                mark++;
                // 2.并将当前遍历到的元素和指针所指元素交换
                int temp = arr[i];
                arr[i] = arr[mark];
                arr[mark] = temp;
            }
        }

        // 遍历结束,将基准元素和指针指向的元素交换,这一轮宣告结束
        arr[startIndex] = arr[mark];
        arr[mark] = standardValue;
        return mark;
    }

    public static void main(String[] args) {
        int[] arr = {5263798410};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    }
}

 思考ing... 

面试官: 不用递归就不会快速排序了? -_-||: 瞧不起谁呢

单边循环法OK了, 双边循环呢?





作者:习惯沉淀,一直在路上的北漂码畜

 Follow Me 
习惯沉淀
一线码农的学习见闻与思考
11篇原创内容
Official Account