我正在练习面试问题。问题是只使用一个堆栈进行临时存储来实现排序堆栈。
实现描述:我正在扩展Stack类以实现我的SortedStack类。 SortedStack类的大多数方法与Stack类相同,因此我不需要实现它们。只覆盖push方法。
在我的实现中,我将当前堆栈传递给push方法。我的问题是:这是访问现有堆栈的最佳方式。我可以访问堆栈的内容而不将其传递给push()方法吗?
Node.java
public class Node {
private int key;
private float value;
public Node(int key, float value) {
this.key = key;
this.value = value;
}
public int getKey() { return key; }
public void setKey(int key) { this.key = key; }
public float getValue() { return value; }
public void setValue(float value) { this.value = value; }
}
SortedStack.java
import java.util.Stack;
public class SortedStack extends Stack {
public SortedStack() {
super();
}
public void push(Stack<Node> mainStack, Node newNode) {
Stack<Node> tempStack = new Stack<Node>();
while (!mainStack.isEmpty()) {
if (mainStack.peek().getKey() > newNode.getKey()) {
tempStack.push(mainStack.pop());
}
else {
break;
}
}
mainStack.push(newNode);
while (!tempStack.isEmpty()) {
mainStack.push(tempStack.pop());
}
}
}
SortedStackApp.java
public class SortedStackApp {
public static void main(String[] args) {
SortedStack stack = new SortedStack();
stack.push(stack, new Node(10, 1.1f));
stack.push(stack, new Node(80, 1.8f));
stack.push(stack, new Node(50, 1.5f));
stack.push(stack, new Node(90, 1.9f));
stack.push(stack, new Node(20, 1.2f));
stack.push(stack, new Node(30, 1.3f));
Node node = null;
while (!stack.isEmpty()) {
node = (Node) stack.pop();
System.out.printf("(%d, %3.1f) ", node.getKey(), node.getValue());
}
System.out.println();
}
}
Stack是java.util.Stack,如:http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html
所述答案 0 :(得分:1)
首先,如果您要扩展java.util.Stack
,则应为其提供基本类型。这是错的:
public class SortedStack extends Stack {...}
在这种情况下,Stack
是原始类型。原始类型应仅与遗留代码一起使用,因为您失去了类型安全性。相反,你应该使用:
public class SortedStack extends Stack<Node> {...}
这样做会自动使您的堆栈仅接受Node
元素。
正如我在评论中所说,你应该覆盖 push
方法,而不是重载它。这意味着它必须具有与父类的push
方法完全相同的参数。因此,它应该只采用Node
参数,就是这样。使用@Override
注释标记方法,以确保您真正覆盖它而不是重载。如果您有额外的参数或不兼容的参数类型,编译器将发出错误。
您将注意到,一旦您这样做,您必须更改方法的声明以返回Node
,因为这是在push
中声明java.util.Stack
的方式。
所以你的方法应该是:
@Override
public Node push(Node n) {
...
}
您应该使用以下代码从main
拨打电话:
stack.push( new Node( 10, 1.1f ) );
由于您已使用该类型正确声明,因此您无需将pop
的结果转换为Node
:
node = stack.pop(); // No need for (Node)
既然我们有一个正确输入的类,那么你的项是堆栈。这就是继承实际上意味着什么:“我现在写的这个类是Stack
并且拥有所有Stack
方法,并且存储了所有Stack
数据,我只是在改变一些它的行为。“
因此,要访问“主”堆栈,只需访问本身即可。例如,while循环应该是:
while (!this.empty()) {
if (this.peek().getKey() > n.getKey()) {
tempStack.push(this.pop());
}
else {
break;
}
}
实际上,你也可以摆脱this
,因为没有歧义。致电empty()
与调用this.empty()
相同(您在代码中使用了isEmpty()
,但java.util.Stack
只有empty()
)。
所以它应该是:
while (!empty() && peek().getKey() > n.getKey() ) {
tempStack.push(pop());
}
(我改进了你的循环,不需要额外的if
)。
但是,请注意使用this.push()
或push()
来获取主堆栈。您可以改用super.push()
。这样它将使用原始行为push
项目进入实际堆栈:
super.push(n); // Don't use new Node() here. Push the node you were given.
while (!tempStack.empty()) {
super.push(tempStack.pop());
}
如果你不这样做,你将以递归方式调用你正在写的push
。这不是你想要的 - 你想要在内部使用“普通”推动。
请务必在完成后返回您插入的Node
。
另一种选择是不扩展Stack
,而是重新实现所有方法并具有内部堆栈。查找“组合与继承”以确定哪个更好。
答案 1 :(得分:-1)
这是唯一的方法。您无法访问直接数据,因为它作为私有存储在节点中,然后发送到堆栈