问题起因
在算法1.2 下压堆栈链表实现过程出, 出现了下面一个问题, 又牵扯出一些新旧问题.
测试函数中的foreach语句不能遍历for (String t : s) {
System.out.println(t);
}
在StackIterator类中, 测试hasNext()方法, print出 “in hasNext() false”, 也就是说迭代不会开始public boolean hasNext() {
System.out.println("in hasNext()" + (current != null));
return current != null;
}
在main函数中, 测试isEmpty(), 这个函数会判断 链表中first指针, 是否为null, 结果打印出 trueStack<String> s = new Stack<String>();
System.out.println(s.isEmpty());
s.push("Truing");
s.push("Dijkstra");
s.push("Kruthun");
System.out.println(s.isEmpty());
找到问题是出在push()函数public void push(Item elem) {
// 向栈中添加元素
Node oldFirst = first;
// Node first = new Node(); // 这样写的逻辑更直观
first = new Node(); // debug: why? 与上一行的区别
first.next = oldFirst;
first.item = elem;
++N;
}
疑惑, 构造一个对象时, 下面两行代码的区别?
public void push(Item elem) { |
上一行导致, first对象指向null, 而下一行的first != null
重新在push方法种进行debug后
public void push(Item elem) { |
空链表push两次:$ java Stack
first ?= null : false
oldFirst ?= null : true
first ?= null : false
oldFirst ?= null : false
public void push(Item elem) { |
空链表push两次:$ java Stack
first ?= null : false
oldFirst ?= null : true
first ?= null : false
oldFirst ?= null : true
问题更进一步
因此, 这两种写法的区别就在于:Node oldFirst = first; // oldFirst指向first对象的引用
Node first = new Node(); // first对象被重新构造, oldFirst指向null
first.next = oldFirst;
此时, 如果oldFirst指向null的话, 将oldFirst作为first的后继, 是不符合我的原意的。
正确的写法是:Node oldFirst = first; // 只是用来保存first对象的引用
first = new Node(); // first指向新的引用对象
first.next = oldFirst; // first.next结点对象指向oldFirst的引用
但为什么既然
oldFirst -> 原来的first对象引用
first->新的对象
oldFirst ?-> 新的结点对象 // why?
如何oldFirst指向新的结点对象的话, 那么对first赋值新的后继, 是永远只能赋值给它自己本身的。。