拉链法哈希表

 拉链法哈希表

 2019-07-03  13:31:32

import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * @ClassName SeparateChainHashST
 * @Author wangyudi
 * @Date 2019/7/2 22:25
 * @Version 1.0
 * @Description 拉链法散列表(哈希表)
 */
public class SeparateChainHashST<Key, Value> {
    private int m;//数组大小
    private int n;//键值对数量
    private Chain<Key, Value>[] st;//存放链表的数组
    private ArrayList<Key> list; //用于迭代获取键的集合

    public SeparateChainHashST() {
        this(997);
    }
    public SeparateChainHashST(int m) {
        this.m = m;
        st = (Chain<Key, Value>[]) new Chain[m]; //实例化数组
        for (int i = 0; i < m; i++) {
            st[i] = new Chain<Key, Value>(); //数组每个元素都指向一个空链表
        }
        this.n = 0;
    }

    public int getSize(){
        return m;
    }

    /**
     * 为了保证每条链的大小保持在2~8,调整数组的大小到size
     * 将源哈希表中所有键值对插入到新哈希表中;然后将新哈希表中的成员给源哈希表
     * @param size
     */
    private void resize(int size){
        SeparateChainHashST<Key, Value> keyValueSeparateChainHashST = new SeparateChainHashST<>(size);
        for(int i=0;i<m;i++){
            for(Object[] o : st[i]){
                keyValueSeparateChainHashST.put((Key)o[0],(Value)o[1]);
            }
        }
        this.m = keyValueSeparateChainHashST.m;
        this.st = keyValueSeparateChainHashST.st;
    }

    /**
     * 返回可迭代的对象
     *
     * @return
     */
    public Iterable<Key> keys() {
        list = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (Object[] o : st[i]) {
                list.add((Key)o[0]);
            }
        }
        return list;
    }

    /**
     * 根据键的hashcode,计算每个键的索引值
     *
     * @param key
     * @return
     */
    private int hash(Key key) {
        return (key.hashCode() & 0x7FFFFFFF) % m;
    }

    /**
     * 向哈希表中放入一个键值对,如果存在相同的键则更新该键的值
     *
     * @param key
     * @param value
     */
    public void put(Key key, Value value) {
        if(n>8*m){
            resize(2*m);
        }
        int i = hash(key);//找到键所在的数组索引
        st[i].put(key, value);//将插入键值对的问题交给链表
        n++;
    }

    /**
     * 根据键,从哈希表获取相应的值;没有该键则返回null
     */
    public Value get(Key key) {
        int i = hash(key);
        return st[i].get(key);
    }

    /**
     * 从哈希表删除键值对,并返回被删除键的值。
     *
     * @param key
     * @return
     */
    public void delete(Key key) {
        int i = hash(key);
        if(st[i].delete(key)){
            n--;
        }
        if(n>0&&n<=2*m){
            resize(m/2);
        }
    }
}


/**
 * 链表类
 *
 * @param <Key>
 * @param <Value>
 */
class Chain<Key, Value> implements Iterable<Object[]> {
    private Node first;

    private class Node {
        Key key;
        Value value;
        Node next;

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

    public Value get(Key key) {
        for (Node i = first; i != null; i = i.next) {
            if (i.key == key) {
                return i.value;
            }
        }
        return null;
    }

    public void put(Key key, Value value) {
        for (Node i = first; i != null; i = i.next) {
            if (i.key == key) {
                i.value = value;
                return; //找到相同的键
            }
        }
        first = new Node(key, value, first);//在头部加入键值队
    }

    /**
     * 删除单向链表中的某一个结点
     *
     * @param key
     * @return
     */
    public boolean delete(Key key) {
//        if (first == null) {
//            return false;
//        }
//        if (first.key == key) {  //判断首结点
//            first = first.next;
//            return true;
//        }
        Node f = null; //保存前一结点的信息
        Node b = first;
        while (b != null && b.key != key) {
            f = b;
            b = b.next;
        }
        if (b != null) { //找到要删除的对象
            if(f==null){
                first=b.next; //特殊处理
            }else {
               f.next = b.next;
            }
            b.next = null;
            b = null;
            return true;
        }
        return false;
    }

    @Override
    public Iterator<Object[]> iterator() {
        return new Iterator() {
            Node i = first;

            @Override
            public boolean hasNext() {
                if (i != null) return true;
                return false;
            }

            @Override
            public Object[] next() {
                Key tempkey = i.key;
                Value tempValue = i.value;
                Object[] info = new Object[]{(Object)tempkey,(Object)tempValue};
                i = i.next;
                return info;
            }
        };
    }
//    public Iterator<Node> nodeIterator(){
//        return new Iterator<Node>() {
//            Node i = first;
//            @Override
//            public boolean hasNext() {
//                if(i!=null)return true;
//                return false;
//            }
//
//            @Override
//            public Node next() {
//                Node temp = i;
//                i = i.next;
//                return temp;
//            }
//        };
//    }
}

 

public class TestCase {
    public static void main(String[] args) {
        SeparateChainHashST<Integer, String> separateChainHashST = new SeparateChainHashST<>(100);
        separateChainHashST.put(12,"12..");
        separateChainHashST.put(2,"2..");
        separateChainHashST.put(34,"34..");
        separateChainHashST.put(17,"17..");
        separateChainHashST.put(55,"55..");
        separateChainHashST.put(214,"214..");
        separateChainHashST.put(12,"12..");
        separateChainHashST.put(2,"2..");
        separateChainHashST.put(34,"34..");
        separateChainHashST.put(17,"17..");
        separateChainHashST.put(55,"55..");
        separateChainHashST.put(214,"214..");
        for(Integer i : separateChainHashST.keys()){
            System.out.println(i);
        }

        System.out.println("===============================================");
        separateChainHashST.delete(34);
        for(Integer i : separateChainHashST.keys()){
            System.out.println(i);
        }
        System.out.println("===============================================");
        System.out.println(separateChainHashST.get(55));
        System.out.println("===============================================");
        System.out.println(separateChainHashST.getSize());
    }
}

//结果
2
12
214
214
17
34
55
===============================================
2
55
12
214
214
17
===============================================
55..
===============================================
50

 

posted @ 2019-07-03 10:52  由走啦啦啦  阅读(243)  评论(0编辑  收藏  举报