zoukankan      html  css  js  c++  java
  • HashTable 实现

    根据冲突解决的不同,可分为seperate chaining hash table, linear probing hash table, quadratic probing hash table.

    自己实现的最简单饿 seperate chaining hash table。

    package ADT;
    
    import java.util.LinkedList;
    /**
     * 自己实现的屌丝版的MySeperateChainingHashTable,
     * 
     * @author jd
     *
     * @param <K>
     * @param <V>
     */
    public class MySeperateChainingHashTable<K, V> {
        private static int M = 10;
        private LinkedList<Entry<K, V>>[] items;
    
        public MySeperateChainingHashTable() {
            items = (LinkedList<Entry<K, V>>[]) (new LinkedList[M]);
            for (int i = 0; i < M; i++) {
                items[i] = new LinkedList<Entry<K, V>>();
            }
        }
    
        public void put(K key, V value) {
            int idx = hash(key);
            LinkedList<Entry<K, V>> list = items[idx];
            for (Entry<K, V> each : list) {
                if (each.key.equals(key)) {
                    each.value = value;
                    return;
                }
            }
    
            list.add(new Entry<K,V>(key, value));
        }
    
        public V get(K key) {
            int idx = hash(key);
            LinkedList<Entry<K, V>> list = items[idx];
            for (Entry<K, V> each : list) {
                if (each.key.equals(key)) {
                    return each.value;
                }
            }
    
            return null;
        }
    
        private int hash(K key) {
            int res = key.hashCode();
            if (res < 0)
                res += M;
            return res % M;
        }
    
        private static class Entry<K, V> {
            public K key;
            public V value;
    
            public Entry(K key, V value) {
                this.key = key;
                this.value = value;
            }
    
        }
    
        public static void main(String[] args) {
            MySeperateChainingHashTable<Integer, String> hashtable = new MySeperateChainingHashTable<Integer, String>();
    
            for (int i = 0; i < 100; i++) {
                hashtable.put(i, i + "" + i);
            }
    
            for (int i = 0; i < 100; i++) {
                System.out.println(hashtable.get(i));
            }
    
        }
    
    }
    View Code

    教材里的范例代码:seperate chaining hash table

    package ADT;
    
    import java.util.LinkedList;
    import java.util.List;
    
    // SeparateChaining Hash table class
    //
    // CONSTRUCTION: an approximate initial size or default of 101
    //
    // ******************PUBLIC OPERATIONS*********************
    // void insert( x )       --> Insert x
    // void remove( x )       --> Remove x
    // boolean contains( x )  --> Return true if x is present
    // void makeEmpty( )      --> Remove all items
    
    /**
     * Separate chaining table implementation of hash tables. Note that all
     * "matching" is based on the equals method.
     * 
     * @author Mark Allen Weiss
     */
    public class SeparateChainingHashTable<T> {
        /**
         * Construct the hash table.
         */
        public SeparateChainingHashTable() {
            this(DEFAULT_TABLE_SIZE);
        }
    
        /**
         * Construct the hash table.
         * 
         * @param size
         *            approximate table size.
         */
        public SeparateChainingHashTable(int size) {
            theLists = new LinkedList[nextPrime(size)];
            for (int i = 0; i < theLists.length; i++)
                theLists[i] = new LinkedList<>();
        }
    
        /**
         * Insert into the hash table. If the item is already present, then do
         * nothing.
         * 
         * @param x
         *            the item to insert.
         */
        public void insert(T x) {
            List<T> whichList = theLists[myhash(x)];
            if (!whichList.contains(x)) {
                whichList.add(x);
    
                // Rehash; see Section 5.5
                if (++currentSize > theLists.length)
                    rehash();
            }
        }
    
        /**
         * Remove from the hash table.
         * 
         * @param x
         *            the item to remove.
         */
        public void remove(T x) {
            List<T> whichList = theLists[myhash(x)];
            if (whichList.contains(x)) {
                whichList.remove(x);
                currentSize--;
            }
        }
    
        /**
         * Find an item in the hash table.
         * 
         * @param x
         *            the item to search for.
         * @return true if x isnot found.
         */
        public boolean contains(T x) {
            List<T> whichList = theLists[myhash(x)];
            return whichList.contains(x);
        }
    
        /**
         * Make the hash table logically empty.
         */
        public void makeEmpty() {
            for (int i = 0; i < theLists.length; i++)
                theLists[i].clear();
            currentSize = 0;
        }
    
        /**
         * A hash routine for String objects.
         * 
         * @param key
         *            the String to hash.
         * @param tableSize
         *            the size of the hash table.
         * @return the hash value.
         */
        public static int hash(String key, int tableSize) {
            int hashVal = 0;
    
            for (int i = 0; i < key.length(); i++)
                hashVal = 37 * hashVal + key.charAt(i);
    
            hashVal %= tableSize;
            if (hashVal < 0)
                hashVal += tableSize;
    
            return hashVal;
        }
    
        private void rehash() {
            List<T>[] oldLists = theLists;
    
            // Create new double-sized, empty table
            theLists = new List[nextPrime(2 * theLists.length)];
            for (int j = 0; j < theLists.length; j++)
                theLists[j] = new LinkedList<>();
    
            // Copy table over
            currentSize = 0;
            for (List<T> list : oldLists)
                for (T item : list)
                    insert(item);
        }
    
        private int myhash(T x) {
            int hashVal = x.hashCode();
    
            hashVal %= theLists.length;
            if (hashVal < 0)
                hashVal += theLists.length;
    
            return hashVal;
        }
    
        private static final int DEFAULT_TABLE_SIZE = 101;
    
        /** The array of Lists. */
        private List<T>[] theLists;
        private int currentSize;
    
        /**
         * Internal method to find a prime number at least as large as n.
         * 
         * @param n
         *            the starting number (must be positive).
         * @return a prime number larger than or equal to n.
         */
        private static int nextPrime(int n) {
            if (n % 2 == 0)
                n++;
    
            for (; !isPrime(n); n += 2)
                ;
    
            return n;
        }
    
        /**
         * Internal method to test if a number is prime. Not an efficient algorithm.
         * 
         * @param n
         *            the number to test.
         * @return the result of the test.
         */
        private static boolean isPrime(int n) {
            if (n == 2 || n == 3)
                return true;
    
            if (n == 1 || n % 2 == 0)
                return false;
    
            for (int i = 3; i * i <= n; i += 2)
                if (n % i == 0)
                    return false;
    
            return true;
        }
    
        // Simple main
        public static void main(String[] args) {
            SeparateChainingHashTable<Integer> H = new SeparateChainingHashTable<>();
    
            long startTime = System.currentTimeMillis();
    
            final int NUMS = 2000000;
            final int GAP = 37;
    
            System.out.println("Checking... (no more output means success)");
    
            for (int i = GAP; i != 0; i = (i + GAP) % NUMS)
                H.insert(i);
            for (int i = 1; i < NUMS; i += 2)
                H.remove(i);
    
            for (int i = 2; i < NUMS; i += 2)
                if (!H.contains(i))
                    System.out.println("Find fails " + i);
    
            for (int i = 1; i < NUMS; i += 2) {
                if (H.contains(i))
                    System.out.println("OOPS!!! " + i);
            }
    
            long endTime = System.currentTimeMillis();
    
            System.out.println("Elapsed time: " + (endTime - startTime));
        }
    
    }
    View Code

    linear probing hash table,注意删除元素后,同一个cluster后面的元素都需要重新hash。

    package ADT;
    
    import java.util.LinkedList;
    import java.util.Queue;
    
    /*************************************************************************
     * Compilation: javac LinearProbingHashST.java Execution: java
     * LinearProbingHashST
     * 
     * Symbol table implementation with linear probing hash table.
     * 
     * % java LinearProbingHashST 128.112.136.11 208.216.181.15 null
     * 
     * 
     *************************************************************************/
    
    public class LinearProbingHashST<Key, Value> {
        private static final int INIT_CAPACITY = 4;
    
        private int N; // number of key-value pairs in the symbol table
        private int M; // size of linear probing table
        private Key[] keys; // the keys
        private Value[] vals; // the values
    
        // create an empty hash table - use 16 as default size
        public LinearProbingHashST() {
            this(INIT_CAPACITY);
        }
    
        // create linear proving hash table of given capacity
        public LinearProbingHashST(int capacity) {
            M = capacity;
            keys = (Key[]) new Object[M];
            vals = (Value[]) new Object[M];
        }
    
        // return the number of key-value pairs in the symbol table
        public int size() {
            return N;
        }
    
        // is the symbol table empty?
        public boolean isEmpty() {
            return size() == 0;
        }
    
        // does a key-value pair with the given key exist in the symbol table?
        public boolean contains(Key key) {
            return get(key) != null;
        }
    
        // hash function for keys - returns value between 0 and M-1
        private int hash(Key key) {
            return (key.hashCode() & 0x7fffffff) % M;
        }
    
        // resize the hash table to the given capacity by re-hashing all of the keys
        private void resize(int capacity) {
            LinearProbingHashST<Key, Value> temp = new LinearProbingHashST<Key, Value>(capacity);
            for (int i = 0; i < M; i++) {
                if (keys[i] != null) {
                    temp.put(keys[i], vals[i]);
                }
            }
            keys = temp.keys;
            vals = temp.vals;
            M = temp.M;
        }
    
        // insert the key-value pair into the symbol table
        public void put(Key key, Value val) {
            if (val == null) {
                delete(key);
                return;
            }
    
            // double table size if 50% full
            if (N >= M / 2)
                resize(2 * M);
    
            int i;
            for (i = hash(key); keys[i] != null; i = (i + 1) % M) {
                if (keys[i].equals(key)) {
                    vals[i] = val;
                    return;
                }
            }
            keys[i] = key;
            vals[i] = val;
            N++;
        }
    
        // return the value associated with the given key, null if no such value
        public Value get(Key key) {
            for (int i = hash(key); keys[i] != null; i = (i + 1) % M)
                if (keys[i].equals(key))
                    return vals[i];
            return null;
        }
    
        // delete the key (and associated value) from the symbol table
        public void delete(Key key) {
            if (!contains(key))
                return;
    
            // find position i of key
            int i = hash(key);
            while (!key.equals(keys[i])) {
                i = (i + 1) % M;
            }
    
            // delete key and associated value
            keys[i] = null;
            vals[i] = null;
    
            // rehash all keys in same cluster
            i = (i + 1) % M;
            while (keys[i] != null) {
                // delete keys[i] an vals[i] and reinsert
                Key keyToRehash = keys[i];
                Value valToRehash = vals[i];
                keys[i] = null;
                vals[i] = null;
                N--;
                put(keyToRehash, valToRehash);
                i = (i + 1) % M;
            }
    
            N--;
    
            // halves size of array if it's 12.5% full or less
            if (N > 0 && N <= M / 8)
                resize(M / 2);
    
            assert check();
        }
    
        // return all of the keys as in Iterable
        public Iterable<Key> keys() {
            Queue<Key> queue = new LinkedList<Key>();
            for (int i = 0; i < M; i++)
                if (keys[i] != null)
                    queue.add(keys[i]);
            return queue;
        }
    
        // integrity check - don't check after each put() because
        // integrity not maintained during a delete()
        private boolean check() {
    
            // check that hash table is at most 50% full
            if (M < 2 * N) {
                System.err.println("Hash table size M = " + M + "; array size N = " + N);
                return false;
            }
    
            // check that each key in table can be found by get()
            for (int i = 0; i < M; i++) {
                if (keys[i] == null)
                    continue;
                else if (get(keys[i]) != vals[i]) {
                    System.err.println("get[" + keys[i] + "] = " + get(keys[i]) + "; vals[i] = " + vals[i]);
                    return false;
                }
            }
            return true;
        }
    
        /***********************************************************************
         * Unit test client.
         ***********************************************************************/
        public static void main(String[] args) {
            LinearProbingHashST<String, Integer> st = new LinearProbingHashST<String, Integer>();
    
        }
    }
    View Code

    quadratic probing hash table.

    package ADT;
    
    // QuadraticProbing Hash table class
    //
    // CONSTRUCTION: an approximate initial size or default of 101
    //
    // ******************PUBLIC OPERATIONS*********************
    // bool insert( x )       --> Insert x
    // bool remove( x )       --> Remove x
    // bool contains( x )     --> Return true if x is present
    // void makeEmpty( )      --> Remove all items
    
    /**
     * Probing table implementation of hash tables. Note that all "matching" is
     * based on the equals method.
     * 
     * @author Mark Allen Weiss
     */
    public class QuadraticProbingHashTable<T> {
        /**
         * Construct the hash table.
         */
        public QuadraticProbingHashTable() {
            this(DEFAULT_TABLE_SIZE);
        }
    
        /**
         * Construct the hash table.
         * 
         * @param size
         *            the approximate initial size.
         */
        public QuadraticProbingHashTable(int size) {
            allocateArray(size);
            doClear();
        }
    
        /**
         * Insert into the hash table. If the item is already present, do nothing.
         * 
         * @param x
         *            the item to insert.
         */
        public boolean insert(T x) {
            // Insert x as active
            int currentPos = findPos(x);
            if (isActive(currentPos))
                return false;
    
            array[currentPos] = new HashEntry<>(x, true);
            theSize++;
    
            // Rehash; see Section 5.5
            if (++occupied > array.length / 2)
                rehash();
    
            return true;
        }
    
        /**
         * Expand the hash table.
         */
        private void rehash() {
            HashEntry<T>[] oldArray = array;
    
            // Create a new double-sized, empty table
            allocateArray(2 * oldArray.length);
            occupied = 0;
            theSize = 0;
    
            // Copy table over
            for (HashEntry<T> entry : oldArray)
                if (entry != null && entry.isActive)
                    insert(entry.element);
        }
    
        /**
         * Method that performs quadratic probing resolution.
         * 
         * @param x
         *            the item to search for.
         * @return the position where the search terminates.
         */
        private int findPos(T x) {
            int offset = 1;
            int currentPos = myhash(x);
    
            while (array[currentPos] != null && !array[currentPos].element.equals(x)) {
                currentPos += offset; // Compute ith probe
                offset += 2;
                if (currentPos >= array.length)
                    currentPos -= array.length;
            }
    
            return currentPos;
        }
    
        /**
         * Remove from the hash table.
         * 
         * @param x
         *            the item to remove.
         * @return true if item removed
         */
        public boolean remove(T x) {
            int currentPos = findPos(x);
            if (isActive(currentPos)) {
                array[currentPos].isActive = false;
                theSize--;
                return true;
            } else
                return false;
        }
    
        /**
         * Get current size.
         * 
         * @return the size.
         */
        public int size() {
            return theSize;
        }
    
        /**
         * Get length of internal table.
         * 
         * @return the size.
         */
        public int capacity() {
            return array.length;
        }
    
        /**
         * Find an item in the hash table.
         * 
         * @param x
         *            the item to search for.
         * @return the matching item.
         */
        public boolean contains(T x) {
            int currentPos = findPos(x);
            return isActive(currentPos);
        }
    
        /**
         * Return true if currentPos exists and is active.
         * 
         * @param currentPos
         *            the result of a call to findPos.
         * @return true if currentPos is active.
         */
        private boolean isActive(int currentPos) {
            return array[currentPos] != null && array[currentPos].isActive;
        }
    
        /**
         * Make the hash table logically empty.
         */
        public void makeEmpty() {
            doClear();
        }
    
        private void doClear() {
            occupied = 0;
            for (int i = 0; i < array.length; i++)
                array[i] = null;
        }
    
        private int myhash(T x) {
            int hashVal = x.hashCode();
    
            hashVal %= array.length;
            if (hashVal < 0)
                hashVal += array.length;
    
            return hashVal;
        }
    
        private static class HashEntry<T> {
            public T element; // the element
            public boolean isActive; // false if marked deleted
    
            public HashEntry(T e) {
                this(e, true);
            }
    
            public HashEntry(T e, boolean i) {
                element = e;
                isActive = i;
            }
        }
    
        private static final int DEFAULT_TABLE_SIZE = 101;
    
        private HashEntry<T>[] array; // The array of elements
        private int occupied; // The number of occupied cells
        private int theSize; // Current size
    
        /**
         * Internal method to allocate array.
         * 
         * @param arraySize
         *            the size of the array.
         */
        private void allocateArray(int arraySize) {
            array = new HashEntry[nextPrime(arraySize)];
        }
    
        /**
         * Internal method to find a prime number at least as large as n.
         * 
         * @param n
         *            the starting number (must be positive).
         * @return a prime number larger than or equal to n.
         */
        private static int nextPrime(int n) {
            if (n % 2 == 0)
                n++;
    
            for (; !isPrime(n); n += 2)
                ;
    
            return n;
        }
    
        /**
         * Internal method to test if a number is prime. Not an efficient algorithm.
         * 
         * @param n
         *            the number to test.
         * @return the result of the test.
         */
        private static boolean isPrime(int n) {
            if (n == 2 || n == 3)
                return true;
    
            if (n == 1 || n % 2 == 0)
                return false;
    
            for (int i = 3; i * i <= n; i += 2)
                if (n % i == 0)
                    return false;
    
            return true;
        }
    
        // Simple main
        public static void main(String[] args) {
            QuadraticProbingHashTable<String> H = new QuadraticProbingHashTable<>();
    
            long startTime = System.currentTimeMillis();
    
            final int NUMS = 2000000;
            final int GAP = 37;
    
            System.out.println("Checking... (no more output means success)");
    
            for (int i = GAP; i != 0; i = (i + GAP) % NUMS)
                H.insert("" + i);
            for (int i = GAP; i != 0; i = (i + GAP) % NUMS)
                if (H.insert("" + i))
                    System.out.println("OOPS!!! " + i);
            for (int i = 1; i < NUMS; i += 2)
                H.remove("" + i);
    
            for (int i = 2; i < NUMS; i += 2)
                if (!H.contains("" + i))
                    System.out.println("Find fails " + i);
    
            for (int i = 1; i < NUMS; i += 2) {
                if (H.contains("" + i))
                    System.out.println("OOPS!!! " + i);
            }
    
            long endTime = System.currentTimeMillis();
    
            System.out.println("Elapsed time: " + (endTime - startTime));
            System.out.println("H size is: " + H.size());
            System.out.println("Array size is: " + H.capacity());
        }
    
    }
    View Code
  • 相关阅读:
    CREATE AGGREGATE
    技术文档列表
    jQuery 判断表单中多个 input text 中至少有一个不为空
    Java实现 蓝桥杯 算法提高 奥运会开幕式
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最大值路径
    Java实现 蓝桥杯 算法提高 最大值路径
    Java实现 蓝桥杯 算法提高 最大值路径
  • 原文地址:https://www.cnblogs.com/jdflyfly/p/3841965.html
Copyright © 2011-2022 走看看