符号表的主要目的是用来存储键值对,也就是将一个键和一个值关联起来,它的主要操作为插入和查找。
这篇只是为下一篇文章作为抛砖引玉,为不熟悉符号表的朋友做了一个大体的介绍,在文章的结尾列出了符号表的基本操作,有一定了解的朋友可以跳的下一篇文章(二叉查找树)。
首先我们必须讨论几个基本问题,这在之后的思想中将会一直用到:
1、重复的键
符号表不允许出现重复的键,当向表中插入的键值对的键已经出现在标中,当前加入的键值对会覆盖原有的键值对,也就是进行了更新。
2、空键或空值
键不能为空,这在java机制中会产生异常。我们还规定,值也不能为空。(get()方法能通过查找键返回其关联的值,当键不存在时get()方法会返回null)
这个规定有两个作用:
第一、我们能判断一个键值对是否存在符号表中。
第二、我们可以将null作为put()的第二个参数来实现删除操作,
3、删除操作
删除操作的实现有两种思路:即时删除和延时删除,延时删除就是上面提到的,先将其值置位为空,然后在某个时刻删除所有值为空的键。即时删除也就是立即从表中删除指定的键。(本文中将使用即时删除)
4、键的等价性
键可以是任意类型(我们将其设置为泛型),可以是integer,double和string等等,java已经为他们实现了equals()方法来判断相等,如果是自定义的键,则需要重写equals()方法。
下面我们进入正题:
一、无序链表中的顺序查找
顾名思义,无序链表就是通常意义上的链表,只是链表的节点被定义为了键值对的形式,无序链表每次插入操作会在头部插入一个新节点,而查找操作是从链表的头部开始一个个地遍历符号表并使用equals()方法来进行匹配。这种方法的效率是非常低的(它的查找操作是线性级别的),查找第一个键需要1次比较,第二个键需要2次比较...因此平均比较次数为(1+2+...+n)/n =(n+1)/2~n/2。它无法适用于大型符号表。
1 public class SequentialSearchST<Key, Value> {// 基于无序链表 2 private int n;// number of key-value pairs 3 private Node first; 4 5 private class Node {// 链表节点的定义 6 Key key; 7 Value val; 8 Node next; 9 10 public Node(Key key, Value val, Node next) { 11 this.key = key; 12 this.val = val; 13 this.next = next; 14 } 15 } 16 17 public Value get(Key key) {// 查找给定的键,返回关联的值 18 for (Node x = first; x != null; x = x.next) { 19 if (key.equals(x.key)) { 20 return x.val; 21 } 22

