IntList L1 = new IntList(5, null);
SLList L2 = new SLList(5);
3.1 addFirst()方法和 getFirst()方法
public class SLList {
public IntNode first;
public SLList(int x) {
first = new IntNode(x, null);
}
//addFirst方法
public void addFirst(int x) {
first = new IntNode(x, first);
}
}
而getFirst()方法也很简单:
public int getFirst() {
return first.item;
}
通过这两个方法,我们可以对比 IntList 和 SLList 创建列表[5,10,15]的区别:
//IntList
IntList L = new IntList(15, null);
L = new IntList(10, L);
L = new IntList(5, L);
int x = L.first;
//SLList
SLList L = new SLList(15);
L.addFirst(10);
L.addFirst(5);
int x = L.getFirst();
3.2 公有类和私有类
如果我们写这样一段代码:
SLList L = new SLList(15);
L.addFirst(10);
L.first.next.next = L.first.next;
那么第二节点就会永远指向第一个节点,而第一个节点优惠指向第二个节点,造成了无限循环。这个错误如果要分析的话,那就是我们不应该可以在类外调用 next 指针,而应该通过方法来修改指针。所以我们需要将IntNode类改成私有类,并提供一些方法来修改指针。
public class SLList {
public static class IntNode {
public int item;
public IntNode next;
public IntNode(int i, IntNode n) {
item = i;
next = n;
}
}
private IntNode first;
public SLList(int x) {
first = new IntNode(x, null);
}
...
}
// 缓存size方法
public class SLList {
...
private IntNode first;
private int size;
public SLList(int x) {
first = new IntNode(x, null);
size = 1;
}
public void addFirst(int x) {
first = new IntNode(x, first);
size += 1;
}
public int size() {
return size;
}
...
}
public void addLast(int x) {
size += 1;
if (first == null) {
first = new IntNode(x, null);
return;
}
IntNode p = first;
while (p.next != null) {
p = p.next;
}
p.next = new IntNode(x, null);
}
但是我们希望得到更加简洁的方法,这时我们可以创建一个指针和节点之间的中间节点,称为哨兵节点。
3.6 哨兵节点
// 哨兵节点
public void addLast(int x) {
size += 1;
IntNode p = sentinel;
while (p.next != null) {
p = p.next;
}
p.next = new IntNode(x, null);
}
public class DLList<T> {
private IntNode sentinel;
private IntNode last;
private int size;
public class IntNode {
public IntNode prev;
public T item;
public IntNode next;
}
}