堆栈可以实现为链表。 可以使用合并排序对链接列表进行排序: O(n log n)时间 O(n)空间
能够使用合并排序对堆栈进行排序是有意义的。
如果是这种情况,代码会是什么样的?
(在网上快速搜索后,我只发现了蛮力算法O(n ^ 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());
}
}