使用链表实现无序符号表SequentialSearchST
这里的关键问题是理解链表以及链表的循环(遍历)
链表实际上就是一个内部类,而且是一个递归结构。未初始化时,链表本身为null(实际上就是在内存中没有分配空间),其中的next也是链表,也是null。
first = new Node(key, value, first);
Node 链表first就被分配了地址,但是first.next仍然时null;
1 class Node<Item> { 2 Item item; 3 Node next; 4 } 5 Node<Integer> first = new Node<>(); 6 Node<Integer> second = new Node<>(); 7 first.item = 1; 8 second.item = 2; 9 first.next = second; 10 System.out.println(second); 11 second = first.next; 12 System.out.println(first.next); 13 System.out.println(second); 14 } 15 /* 16 TestDebug$1Node@2503dbd3 17 TestDebug$1Node@2503dbd3 18 TestDebug$1Node@2503dbd3 19 */
从这个测试中可以看出,first.next = second;是给链表结点赋值指向下一个链表结点。second = first.next;是给链表结点赋上结点的值(或为null赋位置址;或改变结点的位置),这个在循环中是关键。
这两者区别是,前者相当于用一个箭头将自己和另一个结点勾连起来,后者相当于将自己直接变成另一个结点。
1 private Node first; 2 private class Node { 3 Key key; 4 Value value; 5 Node next; 6 //构造函数给链表节点初始化(赋值) 7 public Node(Key key, Value value1, Node next) { 8 this.key = key; //加this是内部类Node的值,另一个是初始化引入的值,同名所以需要区分 9 value = value1; //不同名没有冲突(歧义)就可以不加 10 this.next = next; 11 } 12 } 13 14 /*******最重要:插入、获取、删除符号表中的值***********************/ 15 public void put(Key key, Value value) { 16 for (Node x = first; x != null; x = x.next) { 17 if (key.equals(x.key)) { 18 x.value = value; 19 return; 20 } 21 } 22 first = new Node(key, value, first); 23 } 24 25 public Value get(Key key) { 26 for (Node x = first; x != null; x = x.next) { 27 if (key.equals(x.key)) { 28 return x.value; 29 } 30 } 31 return null; 32 }
首先注意:
新建的链表结点,都是初始化为null,而且程序运行,第一次运行到给first赋值的时候,first.next仍然是null;
for循环: x = x.next;
理解,等号左右两边的x结点是不一样的,左边就是新的结点,右边的x.next是旧的结点的next,指向下一个结点。这个步骤就是将x按顺序转换到下一个结点,像顺着打了很多结点的绳子一节一节向前走。
注意小脚标。这是代表每次运行时,同一个first有不同的值,注意区分。