在堆栈 ADT 的实现中重要的是,您要在哪里添加 push 的新元素,以及要在哪里删除 pop 的元素。显然push(someElement); pop(); 应该保持堆栈不变。
所以我们有 2 个选择,在列表末尾或前面添加/删除元素。
public void push(E element){
stack.add(element);
}
您已选择在列表末尾添加/删除它们。
我不知道add 方法必须做什么,但是如果它返回一个代表新堆栈的新someList,那么私有stack 字段应该分配这个新创建的堆栈!
注意,如果add的目的是改变当前头部(用这个替换当前的TOS(=栈顶)),那么你可以简单地写成如下
public someList<E> add(E newHead){
pop(); // remove TOS
push(newHead); // Add newHead as the new TOS
return this.stack;
}
我已经为String 实现了stack ADT。我把它作为一个简单的练习来改变它以满足您的需求(使用 someList 而不是 List 并使用泛型)。
public class Stack {
private List<String> stack = new ArrayList<String>();
public void push(String element){
stack.add(element);
}
public List<String> add(String newHead){
stack = new ArrayList<String>(stack); // you should do "stack = new someList<E>(newHead, this);"
return stack; // return the new stack
}
public String pop() {
String res = stack.get(stack.size() - 1);
stack.remove(stack.size() - 1); //
return res;
}
public void printStack() {
System.out.println("TOS (Top Of Stack)");
for(int i = stack.size() - 1; i >= 0; i--)
System.out.println(stack.get(i));
System.out.println("EOS (End Of Stack)");
}
}
// Test it
...
String a = "a", b = "b";
Stack stck = new Stack();
stck.push(a);
stck.push(b);
stck.push(b);
stck.push(a);
stck.pop();
stck.printStack();
...
这是测试用例期间堆栈的变化方式。
TOS (Top Of Stack)
a ---> b ---> b ---> a ---> b
a b b b
a b a
a
EOS (End Of Stack)
请注意,在stack ADT 的这个实现中,我们通过从列表尾部添加/删除元素(更准确地说是arrayList)从堆栈中推送/弹出元素。这非常适合与 java 的 arrayList 一起使用,因为在 O(1) 中添加一个元素到列表的尾部或删除最后一个元素。
指定插入位置的方法必须将所有数组元素从插入处复制到右侧
(Source)
在使用自己的 someList 实现时,您必须检查是否同样适用。但是,如果将一个元素添加到列表的尾部(或删除最后一个元素)需要您遍历整个列表(例如,单个链表就是这种情况,因此 O(n)),那么添加/删除第一个元素应该在 O(1) 中。
在这种情况下,您应该更改stack ADT 的实现,以便someList 的前面现在代表TOS,而列表的尾部代表堆栈的末尾。因此 push/pop 将在列表的 front 添加/删除元素。
编辑:您可以实现count 方法:
因此可能的实现
public class Stack {
private List<String> stack = new ArrayList<String>();
...
public int count() {
return stack.size();
}
}