是否可以使用合并排序对堆栈进行排序?

时间:2014-02-21 12:24:41

标签: algorithm sorting

堆栈可以实现为链表。 可以使用合并排序对链接列表进行排序: O(n log n)时间 O(n)空间

能够使用合并排序对堆栈进行排序是有意义的。

如果是这种情况,代码会是什么样的?

(在网上快速搜索后,我只发现了蛮力算法O(n ^ 2))

2 个答案:

答案 0 :(得分:6)

是的,我们可以。诀窍是理解当堆栈被排序时,头部是最大的元素 - 我们想要从低到高迭代它我们可以在O(n)中反转堆栈。

reverse(stack):
   s <- new stack
   while stack.isEmpty() == false:
       s.push(stack.pop)
   return s

现在,使用它,并假设您也可以使用size(),它实现起来相当容易,并且是大多数堆栈实现的标准 - 我们可以实现合并排序:

伪码:

mergeSort(stack):
   if stack.isEmpty():
       return stack
   s1 <- new stack
   s2 <- new stack
   //   O(n):
   while s1.size() < stack.size():
        s1.push(stack.pop())
   while (stack.isEmpty() == false):
        s2.push(stack.pop())           
   mergeSort(s1) //half the size of stack
   mergeSort(s2) //half the size of stack
   //head of s1 and s2 is the largest element
   s1 <- s1.reverse() //easily implemented in O(n)
   s2 <- s2.reverse()
   //now head of s1 and s2 is the smallest element
   while (s1.isEmpty() == false and s2.isEmpty() == false):
        if (s1.peek() < s2.peek()):
            stack.push(s1.pop())
         else:
            stack.push(s2.pop())
   //the 'tail' of one stack:
   while (s1.isEmpty() == false):
         stack.push(s1.pop())
   while (s2.isEmpty() == false):
         stack.push(s2.pop())
   //head is the largest, stacks are sorted
   return stack

<强>正确性:
Base:stop子句是一个空栈,它被排序。
假设:s1和s2被排序。
步骤:在反转之后,当使用pop()方法取下元素时,s1和s2基本上以较低 - >更高的顺序遍历在排序区域中。因为我们总是从每个堆栈插入较小的元素,并且我们遍历每个堆栈从低到高 - 我们得到的结果堆栈是有序的。

<强>复杂度:
不包括递归调用,每一步都是O(stack.size()) = O(n)。这与常规合并排序的行为相同,其余的复杂性遵循原始合并排序的相同步骤来获取O(nlogn)

答案 1 :(得分:1)

也许我会错过这一点,但我会这样做:

void mergesortStack(Stack input) {
    if (input.isEmpty()) {
        return;
    }

    Stack stackLeft = new Stack();
    Stack stackRight = new Stack();

    // split
    while (!input.isEmpty()) {
        stackLeft.push(input.pop());
        if (!input.isEmpty()) {
            stackRight.push(input.pop());
        }
    }

    // recurse
    if (!stackLeft.isEmpty() && !stackRight.isEmpty()) {
        mergesortStack(stackLeft);
        mergesortStack(stackRight);
    }

    // merge
    Stack tmpStack = new Stack();
    while (!stackLeft.isEmpty() || !stackRight.isEmpty()) {
        if (stackLeft.isEmpty()) {
            tmpStack.push(stackRight.pop());
        } else if (stackRight.isEmpty()) {
            tmpStack.push(stackLeft.pop());
            // set an appropriate compare method
        } else if (stackLeft.peek().compareTo(stackRight.peek()) >= 0) {
            tmpStack.push(stackLeft.pop());
        } else {
            tmpStack.push(stackRight.pop());
        }
    }

    // reverse stack
    while (!tmpStack.isEmpty()) {
        input.push(tmpStack.pop());
    }
}