欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构-散列表

程序员文章站 2024-03-16 15:38:46
...

数据结构-散列表

两个重要的问题:

  • 散列函数

  • 散列冲突

    • 散列函数的选择,使得尽可能少的发生散列冲突;
    • 标准的散列关键字是正整数,散列函数可能是整数除以散列表的大小取余;
    • 散列表的大小一般是素数,散列分布的更加均匀;
    • 如果关键字是字符串的话,散列函数可以是把字符串的所有ascII码加起来;

几个散列函数

int hashs1(const string & key, int tablesize){
    int hashval{0};
    for(char x:key){
        hashval+= x;
    }
    return hashval%tablesize;
}

int hashs2(const string& key, int tablesize){
    return (key[0]+27*key[1]+729*key[2])%tablesize;
}

int hashs3(const string& key, int tablesize){
    unsigned int hashval{0};
    for(char ch:key){
        hashval=37*hashval+ch; 
    }
    return hashval%tablesize;
}

如何解决散列冲突

分离链接法

将散列到同一个值的所有元素保存到一个链表中。一个典型的分离链接法哈希表

template<typename HashedObj>
class HashTable{

public:
    explicit HashTable(int size=101);

    bool contains(const HashedObj& x) const;
    void makeEmpty();

    bool insert(const HashedObj& x);
    bool insert(HashedObj&& x);
    bool remove(const HashedObj& x);

private:
    vector<list<HashedObj>> theList;
    int currentSize;
    void rehash();
    size_t myhash(const HashedObj& x);
};

template<typename HashedObj>
void HashTable<HashedObj>::makeEmpty(){
    for(auto& thisList:theList)
        thisList.clear();
} 

template <typename HashedObj>
bool HashTable<HashedObj>::contains(const HashedObj& x){
    auto & whichList = theList[myhash(x)];
    return find(begin(whichList), end(whichList), x) != end(whichList);
}

template<typename HashedObj>
bool HashTable<HashedObj>::remove(const HashedObj& x){

    auto& whichList = theList[myhash(x)];
    auto itr = find(begin(whichList), end(whichList),x);

    if(itr == end(whichList)) return false;

    whichList.erase(itr);
    --currentSize;
    return true;
}

template<typename HashedObj>
bool HashTable<HashedObj>::insert(const HashedObj& x){
    auto & whichList = theList[myhash(x)];
    if(find(begin(whichList),end(whichList),x) != end(whichList())) return false;
    whichList.push_back(x);

    if(++currentSize > theList.size())
        rehash();

    return true;
}