リンクを分離したハーネス・テーブルの使用-データ構造とアルゴリズムの第4版の分析

2977 ワード

/*************************************************************************
	> File Name: HashTable.h
	> Author:keson
	> Mail:[email protected]
	> Created Time: 2014 11 25      21 37 31 
 ************************************************************************/
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
#include<string>
using namespace std;

class hashValue
{
public:
    size_t operator()(const string &key)
    {
        size_t hashVal=0;

        for(auto c:key)
           hashVal=37*hashVal+c;
        return hashVal;
    }
};

template<typename HashedObj>
class HashTable
{
friend class hashValue;
public:
    explicit HashTable(int size=101):theLists(size) {}

    bool contains(const HashedObj &x)const
    {
        auto &whichList=theLists[myhash(x)];
        return find(whichList.begin(),whichList.end(),x)!=whichList.end();
    }

    void print()
    {
         for(auto &thisList:theLists)
            for(auto &x:thisList)
             {cout<<x<<"  ";
                cout<<endl;
             }
    }

    void makeEmpty()
    {
        for(auto &thisList:theLists)
           thisList.clear();
    }

    bool hash_insert(const HashedObj &x)
    {
        auto &whichList=theLists[myhash(x)];
        if(find(begin(whichList),end(whichList),x)!=end(whichList))
           return false;
        whichList.push_back(x);
        if(++currentSize>theLists.size())
           rehash();
        return true;
    }

    bool hash_insert(HashedObj &&x)
    {
        auto &whichList=theLists[myhash(std::move(x))];
        if(find(begin(whichList),end(whichList),x)!=end(whichList))
          return false;
        whichList.push_back(std::move(x));
        if(++currentSize>theLists.size())
         rehash();
        return true;
    }


    bool remove(const HashedObj &x)
    {
        auto &whichList=theLists[myhash(x)];
        auto itr=find(whichList.begin(),whichList.end(),x);

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

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


private:
    vector<list<HashedObj>> theLists;
    int currentSize;

    void rehash()
    {
        vector<list<HashedObj>> oldLists=theLists;
        //create new double-sized,empty table
        theLists.resize(2*theLists.size());

        for(auto &thisList:theLists)
            thisList.clear();

        //copy table over
        currentSize=0;
        for(auto &thisList:oldLists)
           for(auto &x:thisList)
              hash_insert(std::move(x));
    }

    size_t myhash(const HashedObj &x) const
    {
       static    hashValue hf;
        return hf(x)%theLists.size();
    }

};

int main()
{
    HashTable<string>  a;
    a.hash_insert("abc");
    a.print();


}