Java集合之Hashtable理论(散列表)

除了使用链表的方法,更多的是用开放寻址法

  • 线性寻址

    \(LH(k,0)=H(k)\)确定了整个探查序列,只有m种不同的探查序列

  • 二次寻址

    \(QH(k,i)=\{H(k)+c_1*i+c_2*i^2\} \pmod m\),其中\(c_1\)\(c_2\)是两个不为0的常数。若取\(c_1=c_2=1\),二次探查的散列函数为:

    private int QH(int value, int i)
    {
        return (H(value) + i + i * i) % 10;
    }
    

    对于数值 7,\(QH()\)给出的探查序列是 7、9、3、9……由于初始位置\(QH(k, 0) = H(k)\)确定了整个探查序列,所以二次探查同样只有 m 种不同的探查序列。通过让下一个探查位置以 i 的平方偏移,不容易像线性探查那样让被占用的槽连成一片。

  • 双重寻址

    \(H(k,i)=\{H_1(k)+i*H_2(k)\} \pmod m\)

    其中:

    \(H_1(k)=k \pmod m\)

    \(H_2(k)=1+\{k \pmod {m-1}\}\)

    int H1(int value)
        {
            return value % _values.Length;
        }
        int H2(int value)
        {
            return 1 + (value % (_values.Length - 1));
        }
        int DH(int value, int i)
        {
            return (H1(value) + i * H2(value)) % _values.Length;
        }
     
        public void Add(int item)
        {
            int i = 0; // 已经探查过的槽的数量
            do
            {
                int j = DH(item, i); // 想要探查的地址
                if (_values[j] == null || (int)_values[j] == DELETED)
                {
                    _values[j] = item;
                    return;
                }
                else
                {
                    i += 1;
                }
            } while (i <= _values.Length);
            throw new Exception("集合溢出");
        }
        public bool Contains(int item)
        {
            int i = 0; // 已经探查过的槽的数量
            int j = 0; // 想要探查的地址
            do
            {
                j = DH(item, i);
                if (_values[j] == null)
                    return false;
     
                if ((int)_values[j] == item)
                    return true;
                else
                    i += 1;
            } while (i <= _values.Length);
            return false;
        }
        public void Remove(int item)
        {
            int i = 0; // 已经探查过的槽的数量
            int j = 0; // 想要探查的地址
            do
            {
                j = DH(item, i);
                if (_values[j] == null)
                    return;
     
                if ((int)_values[j] == item)
                {
                    _values[j] = DELETED;
                    return;
                }
                else
                {
                    i += 1;
                }
            } while (i <= _values.Length);
        }
    

总结

  此算法(双重探查)在C#中实现,但是在Java的Hashtable源码中,是以单向链表的方式实现hashtable(哈希表)的。

posted @ 2020-04-21 21:08  程序员曾奈斯  阅读(153)  评论(0编辑  收藏  举报