• 简单哈希表学习


    原文地址:https://blog.csdn.net/Hu_weichen/article/details/80820728

    自己输入跑了一下:

    #include <vector>
    #define NULLKEY - 32768

    class HashTable
    {
    public:
        HashTable(int n);
        ~HashTable();
        void InsertHash(int key);
        int searchHash(int key);
        void show();
    private:
        int hash(int key);
        vector<int> elem;
        int count;
        int m;
    };

    HashTable::HashTable(int n):count(0),m(n)
    {
        for(int i =0 ;i <n;++i)
        {
            elem.push_back(NULLKEY);
        }
    }

    HashTable::~HashTable()
    {}

    int HashTable::hash(int key)
    {
        return key % m;
    }

    void HashTable::InsertHash(int key)
    {
        int addr = hash(key);
        while(NULLKEY != elem[addr])
        {
            addr = (addr+1)%m;
        }
        elem[addr] = key;
        count++;
    }

    int HashTable::searchHash(int key)
    {
        int addr = hash(key);
        while(elem[addr] != key)
        {
            addr = (addr +1)%m;
            if(NULLKEY == elem[addr] || hash(key) == addr)
            {
                return -1;
            }
        }
        return addr;
    }

    void HashTable::show()
    {
        for(int i = 0;i < m;i++)
        {
            cout << elem[i]<<endl;
        }
    }

    int main()
    {
        int n,e,val;
        vector<int> vec;
        cout << "输入元素个数:";
        cin >> n;
        cout << "输入数据元素:"<<endl;
        for(int i = 0; i < n ;i++)
        {
            cin >>e;
            vec.push_back(e);
        }
        HashTable H(n);
        for(int i =0;i<n;++i)
        {
            H.InsertHash(vec[i]);
        }
        cout<<"散列表"<<endl;
        H.show();
        while(1)
        {
            cout<<"输入要查找的数据元素:";
            cin>>val;
            e= H.searchHash(val);
            if(-1 == e)
            {
                break;
                cout<<"look up failed!"<<endl;
            }
            else
            {
                cout<<"下标为:"<<e<<endl;
            }
        }
        system("pause");
    }

    以上是原文代码,主要说下自己输入的一点理解。

    代码首先是构造了一个长度固定的vector来存储key值,当然这个固定的长度n也是手动输入的

    散列函数用的是除留余数法

    int HashTable::hash(int key)
    {
        return key % m;
    }

    主要是为了收敛key对应的地址,f(key)的值在0~m-1之间

    插值函数:

    void HashTable::InsertHash(int key)
    {
        int addr = hash(key);
        while(NULLKEY != elem[addr])
        {
            addr = (addr+1)%m;
        }
        elem[addr] = key;
        count++;
    }

    得到key的哈希地址addr之后,如果elem[addr]尚未被填充数据,则elem[addr] = key,否则addr加上一个偏移量继续直到找到未被填充数据的elem[addr], 原文这里addr = (addr+1)%key显然不对,因为地址显然在0~(m-1)之间移动,已修正

    查找函数:

    int HashTable::searchHash(int key)
    {
        int addr = hash(key);
        while(elem[addr] != key)
        {
            addr = (addr +1)%m;
            if(NULLKEY == elem[addr] || hash(key) == addr)
            {
                return -1;
            }
        }
        return addr;
    }

    这个函数是整个里面唯一不太好理解的,这个要结合插值函数看,首先如果这个查询的key值存在对应的地址对应,那么在不断的偏移判断elem[addr] 是否为key的循环中,定然能找到elem[addr] = key的addr值,所以第一次情况如果NULLKEY == elem[addr] 了都没有将key值插入这个存储数组中,那显然这个key并没有对应的地址,这种情况存储的key地址对是小于m的,所以存在未填充key的地方,所以还存在第二种情形,key地址对与m,n是相等的,elem[]数组被填充满,addr+1地址从0~m-1遍历了一遍任未找到elem[addr] = key,然后又回到了0(假设从第一次哈希运算得到0),这时使得hash(key) == addr又重新成立,此种情形也能说明哈希表中不存在这个key值。

  • 相关阅读:
    EasyNetQ使用(八)【对延迟消息插件的支持,自动订阅者】
    EasyNetQ使用(七)【发布者确认 ,用Future Publish发布预定中事件 】
    EasyNetQ使用(六)【多态发布和订阅,消息版本控制】
    EasyNetQ使用(五)【基于主题的路由,控制队列名称】
    EasyNetQ使用(四)【Request与Response,Send与Receive】
    可伸缩系统的架构经验
    Stack Exchange 的架构
    Quora使用到的技术
    Digg工程师讲述Digg背后的技术
    由12306.cn谈谈网站性能技术
  • 原文地址:https://www.cnblogs.com/doulcl/p/10907517.html
Copyright © 2020-2023  润新知