顺序查找(基于无序链表)

非常低效,见p238图3.1.3

  1. public class SequentialSearchST<Key, Value>
  2. {
  3. private Node first; // 链表首节点
  4. private class Node;
  5. { // 链表结点的定义
  6. Key key;
  7. Value val;
  8. Node next;
  9. public Node(Key key, Value val, Node next)
  10. {
  11. this.key = key;
  12. this.val = val;
  13. this.next = next;
  14. }
  15. }
  16. public Value get(Key key)
  17. { // 查找给定的键,返回关联的值
  18. for (Node x = first; x != null; x = x.next)
  19. if (key.equals(x.key))
  20. return x.val; // 命中
  21. return null // 未命中
  22. }
  23. public void put(Key key, Value val)
  24. { // 查找给定的键,找到则更新其值,否则在表中新建结点
  25. for (Node x = first; x != null; x = x.next)
  26. if (key.equals(x.key)) {
  27. x.val = val;
  28. return;
  29. }
  30. first = new Node(key, val, first); // 未命中,新建结点
  31. }
  32. }

有序数组中的二分查找

  1. public class BinarySearchST<Key extends Comparable<Key>, Value> // 有序符号表api实现
  2. {
  3. private Key[] keys;
  4. private Value[] vals;
  5. private int N;
  6. public BinarySearchST(int capacity)
  7. {
  8. keys = (Key[]) new Comparable[capacity];
  9. vals = (Value[]) new Object[capacity];
  10. }
  11. public int size()
  12. {
  13. return N;
  14. }
  15. public Value get(Key key)
  16. {
  17. if (isEmpty()) return null;
  18. int i = rank(key);
  19. if (i < N && keys[i].compareTo(key) == 0)
  20. return vals[i];
  21. else
  22. return null;
  23. }
  24. public int rank(Key key)
  25. {
  26. int lo = 0, hi = N - 1;
  27. while (lo <= hi)
  28. {
  29. int mid = lo + (hi - lo) / 2;
  30. int cmp = key.compateTo(keys[mid]);
  31. if (cmp < 0) hi = mid - 1;
  32. else if (cmp > 0) lo = mid + 1;
  33. else return mid;
  34. }
  35. return lo;
  36. }
  37. public void put(Key key, Value val)
  38. { // 查找键,找到则更新值,否则创建新的元素
  39. int i = rank(key);
  40. if (i < N && keys[i].compareTo(key) == 0)
  41. {
  42. vals[i] = val; return;
  43. }
  44. for (int j = N; j > i; j--)
  45. {
  46. keys[j] = keys[j - 1];
  47. vals[j] = vals[j - 1];
  48. }
  49. keys[i] = key;
  50. vals[i] = val;
  51. N++;
  52. }
  53. public void delete(Key key)
  54. {
  55. // TODO
  56. }
  57. }

更高效的查找

为了将二分查找的效率和链表的灵活性结合起来,我们需要更加复杂的数据结构,二叉树查找

符号表的各种实现的优缺点

使用的数据结构 实现 优点 缺点
链表(顺序查找) SequentialSearchST 适用于小型问题 对于大型符号表很慢
有序数组(二分查找) BinarySearchST 最有的查找效率和空间需求,能够进行有序性相关的操作 插入操作很慢
二叉树查找 BST 实现简单,能够进行有序性相关的操作 没有性能上界的保证
平衡二叉树查找 RedBlackBST 最优的查找和插入效率,能够进行有序性相关的操作 链接需要额外的空间
散列表 SeparateChainHashST
能够快速的查找和插入常见数据类型 需要计算每种类型的数据的散列无法进行有序性相关的操作