1 Symbol table

1 application & define

  • Key-value pair abstraction.
  • ・Insert a value with specified key.
  • ・Given a key, search for the corresponding value.

1 application

  • Ex. DNS lookup.
  • ・Insert domain name with specified IP address.
  • ・Given domain name, find corresponding IP address

  • web search

2 实现

  1. public class ST<Key extends Comparable<Key>, Value> implements Iterable<Key> {
  2. private TreeMap<Key, Value> st;
  3. /**
  4. * Initializes an empty symbol table.
  5. */
  6. public ST() {
  7. st = new TreeMap<Key, Value>();
  8. }
  9. public Value get(Key key) {
  10. if (key == null)
  11. throw new IllegalArgumentException("calls get() with null key");
  12. return st.get(key);
  13. }
  14. public void put(Key key, Value val) {
  15. if (key == null)
  16. throw new IllegalArgumentException("calls put() with null key");
  17. if (val == null) st.remove(key);
  18. else st.put(key, val);
  19. }
  20. public void delete(Key key) {
  21. if (key == null)
  22. throw new IllegalArgumentException("calls delete() with null key");
  23. st.remove(key);
  24. }
  25. public boolean contains(Key key) {
  26. if (key == null)
  27. throw new IllegalArgumentException("calls contains() with null key");
  28. return st.containsKey(key);
  29. }
  30. public int size() {
  31. return st.size();
  32. }
  33. public boolean isEmpty() {
  34. return size() == 0;
  35. }
  36. /**
  37. * Returns all keys in this symbol table.
  38. * <p>
  39. * To iterate over all of the keys in the symbol table named {@code st},
  40. * use the foreach notation: {@code for (Key key : st.keys())}.
  41. *
  42. * @return all keys in this symbol table
  43. */
  44. public Iterable<Key> keys() {
  45. return st.keySet();
  46. }
  47. /**
  48. * Returns all of the keys in this symbol table.
  49. * To iterate over all of the keys in a symbol table named {@code st}, use the
  50. * foreach notation: {@code for (Key key : st)}.
  51. * <p>
  52. * This method is provided for backward compatibility with the version from
  53. * <em>Introduction to Programming in Java: An Interdisciplinary Approach.</em>
  54. *
  55. * @return an iterator to all of the keys in this symbol table
  56. * @deprecated Replaced by {@link #keys()}.
  57. */
  58. @Deprecated
  59. public Iterator<Key> iterator() {
  60. return st.keySet().iterator();
  61. }
  62. /**
  63. * Returns the smallest key in this symbol table.
  64. *
  65. * @return the smallest key in this symbol table
  66. * @throws NoSuchElementException if this symbol table is empty
  67. */
  68. public Key min() {
  69. if (isEmpty())
  70. throw new NoSuchElementException("calls min() with empty symbol table");
  71. return st.firstKey();
  72. }
  73. /**
  74. * Returns the largest key in this symbol table.
  75. *
  76. * @return the largest key in this symbol table
  77. * @throws NoSuchElementException if this symbol table is empty
  78. */
  79. public Key max() {
  80. if (isEmpty())
  81. throw new NoSuchElementException("calls max() with empty symbol table");
  82. return st.lastKey();
  83. }
  84. /**
  85. * Returns the smallest key in this symbol table greater than or equal to {@code key}.
  86. *
  87. * @param key the key
  88. * @return the smallest key in this symbol table greater than or equal to {@code key}
  89. * @throws NoSuchElementException if there is no such key
  90. * @throws IllegalArgumentException if {@code key} is {@code null}
  91. */
  92. public Key ceiling(Key key) {
  93. if (key == null) throw new IllegalArgumentException("argument to ceiling() is null");
  94. Key k = st.ceilingKey(key);
  95. if (k == null) throw new NoSuchElementException("all keys are less than " + key);
  96. return k;
  97. }
  98. /**
  99. * Returns the largest key in this symbol table less than or equal to {@code key}.
  100. *
  101. * @param key the key
  102. * @return the largest key in this symbol table less than or equal to {@code key}
  103. * @throws NoSuchElementException if there is no such key
  104. * @throws IllegalArgumentException if {@code key} is {@code null}
  105. */
  106. public Key floor(Key key) {
  107. if (key == null)
  108. throw new IllegalArgumentException("argument to floor() is null");
  109. Key k = st.floorKey(key);
  110. if (k == null)
  111. throw new NoSuchElementException("all keys are greater than " + key);
  112. return k;
  113. }
  114. /**
  115. * Unit tests the {@code ST} data type.
  116. *
  117. * @param args the command-line arguments
  118. */
  119. public static void main(String[] args) {
  120. ST<String, Integer> st = new ST<String, Integer>();
  121. for (int i = 0; !StdIn.isEmpty(); i++) {
  122. String key = StdIn.readString();
  123. st.put(key, i);
  124. }
  125. for (String s : st.keys())
  126. StdOut.println(s + " " + st.get(s));
  127. }
  128. }

2 线性表

  • 主要API
  • get
  • put
  • delete
  • contains
  • isEmpty
  • Keys() =>遍历键

sq .png·

public class SequentialSearchST<Key, Value> {
    private int n;           // number of key-value pairs
    private Node first;      // the linked list of key-value pairs

    // a helper linked list data type
    private class Node {
        private Key key;
        private Value val;
        private Node next;

        public Node(Key key, Value val, Node next)  {
            this.key  = key;
            this.val  = val;
            this.next = next;
        }
    }

    /**
     * Initializes an empty symbol table.
     */
    public SequentialSearchST() {
    }

    /**
     * Returns the number of key-value pairs in this symbol table.
     *
     * @return the number of key-value pairs in this symbol table
     */
    public int size() {
        return n;
    }

    /**
     * Returns true if this symbol table is empty.
     *
     * @return {@code true} if this symbol table is empty;
     *         {@code false} otherwise
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * Returns true if this symbol table contains the specified key.
     *
     * @param  key the key
     * @return {@code true} if this symbol table contains {@code key};
     *         {@code false} otherwise
     * @throws IllegalArgumentException if {@code key} is {@code null}
     */
    public boolean contains(Key key) {
        if (key == null) 
            throw new IllegalArgumentException("argument to contains() is null");
        return get(key) != null;
    }

    /**
     * Returns the value associated with the given key in this symbol table.
     *
     * @param  key the key
     * @return the value associated with the given key if the key is in the symbol table
     *     and {@code null} if the key is not in the symbol table
     * @throws IllegalArgumentException if {@code key} is {@code null}
     */
    public Value get(Key key) {
        if (key == null) 
            throw new IllegalArgumentException("argument to get() is null"); 
        for (Node x = first; x != null; x = x.next) {
            if (key.equals(x.key))
                return x.val;
        }
        return null;
    }

    /**
     * Inserts the specified key-value pair into the symbol table, overwriting the old 
     * value with the new value if the symbol table already contains the specified key.
     * Deletes the specified key (and its associated value) from this symbol table
     * if the specified value is {@code null}.
     *
     * @param  key the key
     * @param  val the value
     * @throws IllegalArgumentException if {@code key} is {@code null}
     */
    public void put(Key key, Value val) {
        if (key == null) 
            throw new IllegalArgumentException("first argument to put() is null"); 
        if (val == null) {
            delete(key);
            return;
        }

        for (Node x = first; x != null; x = x.next) {
            if (key.equals(x.key)) {
                x.val = val;
                return;
            }
        }
        first = new Node(key, val, first);
        n++;
    }

    /**
     * Removes the specified key and its associated value from this symbol table     
     * (if the key is in this symbol table).    
     *
     * @param  key the key
     * @throws IllegalArgumentException if {@code key} is {@code null}
     */
    public void delete(Key key) {
        if (key == null) 
            throw new IllegalArgumentException("argument to delete() is null"); 
        first = delete(first, key);
    }

    // delete key in linked list beginning at Node x
    // warning: function call stack too large if table is large
    private Node delete(Node x, Key key) {
        if (x == null) return null;
        if (key.equals(x.key)) {
            n--;
            return x.next;
        }
        x.next = delete(x.next, key);
        return x;
    }


    /**
     * Returns all keys in the symbol table as an {@code Iterable}.
     * To iterate over all of the keys in the symbol table named {@code st},
     * use the foreach notation: {@code for (Key key : st.keys())}.
     *
     * @return all keys in the symbol table
     */
    public Iterable<Key> c()  {
        Queue<Key> queue = new Queue<Key>();
        for (Node x = first; x != null; x = x.next)
            queue.enqueue(x.key);
        return queue;
    }


    /**
     * Unit tests the {@code SequentialSearchST} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        SequentialSearchST<String, Integer> st = new SequentialSearchST<String, Integer>();
        for (int i = 0; !StdIn.isEmpty(); i++) {
            String key = StdIn.readString();
            st.put(key, i);
        }
        for (String s : st.keys())
            StdOut.println(s + " " + st.get(s));
    }
}