hashtable模板的簡單實現

hashtable模板的簡單實現

知識標籤: hashtable, template, 函數指針, hash, C++, container, C++11

轉載註明鏈接出處

代碼中有註釋,直接上代碼:

hashtable.h如下:

#ifndef __HASHTABLE_H__
#define __HASHTABLE_H__

#include<vector>
#include<list>

template<typename T>
class hashtable
{
    public:

        typedef size_t (*HT)(const T&);

        //構造函數,初始化list數組大小,hashtable元素個數,哈希函數
        //參數numLists = 100一定要放後面,因爲它有默認值
        hashtable(HT ht, size_t numLists = 100) : TLists(numLists), m_num(0), phash(ht){}

        ~hashtable(){}

        bool isin(const T& t)
        {//判斷t是否在hashtable中
            std::list<T>& alist = TLists[myhash(t)];
            if(alist.end() == contain(t))
                return false;
            else
                return true;
        }

        //插入一個hashtable中不存在的值
        bool insert_unique(T& t)
        {
            std::list<T>& alist = TLists[myhash(t)];
            if(contain(t) != alist.end())
            {
                return false;
            }

            insert(t);
        }

        //插入一個hashtable中可能存在的值,不檢查唯一性
        void insert(T& t)
        {
            //負載係數(loading factor),意指元素個數除以表格大小。此負載係數不大於1
            //如果當前hashtable中元素個數大於vector的大小
            if(m_num + 1 > TLists.size())
            {
                resize2();
            }

            //這句代碼不能寫在if上面
            std::list<T>& alist = TLists[myhash(t)];
            alist.push_back(t);
            ++m_num;
        }

        //刪除一個元素
        bool remove(const T& t)
        {
            std::list<T>& alist = TLists[myhash(t)];
            typename std::list<T>::iterator iter = contain(t);
            if(iter == alist.end())
            {
                return false;
            }
            else
            {
                alist.erase(iter);
                --m_num;
                return true;
            }
        }

        //清空hashtable
        bool clear()
        {
            typename std::vector<std::list<T> >::iterator iter = TLists.begin();
            //遍歷list數組
            while(iter != TLists.end())
            {
                (*iter++).clear();
            }
            m_num = 0;
        }

        //依次打印hashtable所有元素
        void show()
        {
            typename std::vector<std::list<T> >::iterator i = TLists.begin();
            typename std::list<T>::iterator j;
            while(i != TLists.end())
            {
                j = (*i).begin();
                while(j != (*i).end())
                {
                    //注:T類型必須支持operator<<
                    std::cout << *j++ << '\t' << std::flush;
                }
                std::cout << std::endl;
                ++i;
            }

            std::cout << "m_num = " << m_num << std::endl;
            std::cout << "TLists.size() : " << TLists.size() << std::endl;
        }

    private:

        //list數組, hashtable存儲結構
        std::vector<std::list<T> > TLists;
        size_t m_num;   //hashtable中元素個數

        //函數指針,類型T的hash函數
        size_t (*phash)(const T&);

    private:

        //判斷t是否在hashtable中
        typename std::list<T>::iterator contain(const T& t)
        {
            std::list<T>& alist = TLists[myhash(t)];

            typename std::list<T>::iterator iter= alist.begin();
            while(iter != alist.end())
            {
                //注意:類型T必須有==運算符
                if(t == *iter)
                {
                    return iter;
                }
                ++iter;
            }
            return alist.end();
        }

        //hashtable自增長爲原先2倍大小
        void resize2()
        {
            //備份
            std::vector<std::list<T> > oldLists = TLists;
            //擴容
            TLists.resize(2 * TLists.size());
            typename std::vector<std::list<T> >::iterator iter_new = TLists.begin();
            while(iter_new != TLists.end())
            {
                (*iter_new++).clear();
            }
            m_num = 0;

            //遍歷hashtable,把所有元素插入新hashtable
            typename std::vector<std::list<T> >::iterator i = oldLists.begin();
            typename std::list<T>::iterator j;
            while(i != oldLists.end())
            {
                j = (*i).begin();
                while(j != (*i).end())
                {
                    insert(*j++);
                }
                ++i;
            }
        }

        size_t myhash(const  T& t)
        {//返回list數組下標
            size_t val_hash = phash(t);
            val_hash = val_hash % TLists.size();
            return val_hash;
        }
};

#endif

main.cpp文件如下:

#include<iostream>
#include<string>
#include<functional>
#include "hashtable.h"

class node
{
    public:

        node(std::string st, size_t sc)
        {
            str = st;
            score = sc;
        }

        friend std::ostream& operator<<(std::ostream& fout, node nd);
        friend bool operator==(node nd1, node nd2);

        std::string str;
        size_t score;
};

std::ostream& operator<<(std::ostream& out, node nd)
{
    out << "( " << nd.str << ", " << nd.score << " )";
}

bool operator==(node nd1, node nd2)
{
    if(nd1.str == nd2.str)
    {
        return true;
    }
    else
    {
        return false;
    }
}

size_t myhash(const node& nd)
{
    //利用string字段返回hash值
    return std::hash<std::string>()(nd.str);
}

int main(void)
{
    hashtable<node> ht(&myhash, 6);

    node nd1("小明", 66);
    node nd2("小花", 77);
    node nd3("小紅", 88);
    node nd4("小王", 56);
    node nd5("小李", 99);
    node nd6("小時", 100);
    node nd7("小周", 90);
    node nd8("小郭", 67);
    node nd9("小吳", 87);
    node nd10("小馬", 79);
    node nd11("小黃", 92);

    ht.insert(nd1);
    ht.insert(nd2);
    ht.insert(nd3);
    ht.insert(nd4);
    ht.insert(nd5);
    ht.insert(nd6);
    ht.insert(nd7);
    ht.insert(nd8);
    ht.insert(nd9);
    ht.insert(nd10);
    ht.insert(nd11);
    ht.show();

    std::cout << "----------------------------" << std::endl;
    ht.remove(nd3);
    if(ht.isin(nd3))
        std::cout<< "nd3 is in hashtable !" << std::endl;
    else
        std::cout << "nd3 is not in hashtable !" << std::endl;

    std::cout << "----------------------------" << std::endl;
    ht.clear();
    ht.show();

    return 0;
}

編譯如下:

g++ main.cpp -o main -std=c++11

我在代碼中用到了C++11標準,所以編譯時添加-std=c++11

結果截屏:
hashtable結果

發佈了26 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章