【问题标题】:Using Stacks for a Non-Recursive MergeSort?使用堆栈进行非递归合并排序?
【发布时间】:2014-03-20 18:27:26
【问题描述】:

我的教授分配了一个问题,我们必须使用堆栈(或队列)来进行非递归合并排序。当前代码如下:

 private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) {
    if (hi <= lo) return;
    int mid = lo + (hi - lo) / 2;

    sort(a, index, aux, lo, mid);
    sort(a, index, aux, mid + 1, hi);

    merge(a, index, aux, lo, mid, hi);

我不确定如何解决这个问题,如果有任何帮助,我将不胜感激。我知道我必须使用 while 循环来模拟递归。但是如何拆分实际值?另外,如何跟踪分区值的中间值?

我真的被这个问题搞糊涂了。任何帮助,将不胜感激!

【问题讨论】:

  • 想想递归是如何工作的——将当前状态压入程序堆栈,处理新的数据子集,将结果返回给调用者,将先前的状态从堆栈中弹出并继续.在本练习中,您真正要做的就是将 call/return 替换为 push-iterate-pop。

标签: java


【解决方案1】:

最重要的是了解算法的工作原理。来自Wikipedia

从概念上讲,归并排序的工作原理如下:

将未排序的列表分成 n 个子列表,每个子列表包含 1 个元素(a 1 个元素的列表被认为是已排序的)。反复合并子列表到 生成新的排序子列表,直到只剩下 1 个子列表。 这将是排序列表。

解决方案 1:使用队列。


static int[] mergeSortQueue(int[] A) {
        Queue<int[]> queue = new LinkedList<int[]>();


        for (int i = 0; i < A.length; i++)
        {
            queue.add(new int[]{A[i]});
        }
        while (queue.size()>1)
        {
                int[] r = queue.poll();
                int[] l = queue.poll();
                int[] merged=merge(l, r);
                queue.add(merged);  
        }
        return queue.poll();


    }

图形化,


解决方案 2:使用两个堆栈


这有点复杂。

它基本上包括合并第一个堆栈的元素,将它们插入第二个堆栈,直到只剩下一个。

static int[] mergeSortStacks(int[] A) {
        Stack<int[]> stack = new Stack<int[]>();
        Stack<int[]> stack2 = new Stack<int[]>();

        for (int i = 0; i < A.length; i++)
        {
            stack.push(new int[]{A[i]});
        }
        while (stack.size()>1)
        {
            while (stack.size()>1)
            {

                int[] r = stack.pop();
                int[] l = stack.pop();
                int[] merged=merge(l, r);
                stack2.push(merged);
            }
            while (stack2.size()>1)
            {

                int[] r = stack2.pop();
                int[] l = stack2.pop();
                int[] merged=merge(l, r);
                stack.push(merged);
            }
        }
        return stack.isEmpty() ? stack2.pop() : stack.pop();


    }

图形化,

【讨论】:

  • 精彩的回复,谢谢!但是,您的两个堆栈示例不适用于[7, 1, 5, 2, 9, 3] 之类的数组,因为当循环完成时,两个堆栈都将包含一个数组。所以你可以在你的退货声明之前添加if (!stack.isEmpty() &amp;&amp; !stack2.isEmpty()) return merge(stack.pop(), stack2.pop());
  • 我认为两个堆栈方法会产生 n^2 运行时间,因为它总是将一个大数组与一个或两个元素数组合并。
  • 嗯,比这少一点。应该接近 n*log(n) 运行时间
猜你喜欢
  • 2019-05-05
  • 2023-04-11
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-15
  • 2010-12-06
  • 1970-01-01
相关资源
最近更新 更多