ハッシュマップを使用して、簡単なアプリケーション----簡単なハッシュテーブルを達成するためにHashTbleデータ構造(ハッシュテーブル)

ハッシュマップを達成するために、単純なハッシュテーブルを持ちます

参考サイト

  1. https://blog.csdn.net/stpeace/article/details/81274233
  2. https://blog.csdn.net/qq_36221862/article/details/73488162
  3. https://blog.csdn.net/xyzbaihaiping/article/details/51607770

理論的な知識・ハッシュ・テーブル

ここにあるハッシュテーブルとの間の関係の基礎は詳述されていません

ハッシュテーブルのシンプルなアプリケーション

基づいHashMapを達成するために、単純なハッシュテーブル(ジッパー方法)

参照だけのためのコード:GitHubのアドレス

#include <iostream>
#include <string>
#include <memory>
#include <functional>

using namespace std;

//hash table 内部节点
template <typename T,typename U>
class Node{
public:
    Node(const T& key,const T& value){
        m_key = key;
        m_value = value;
    }
    ~Node(){
        std::cout<<"~Node()"<<std::endl;
    }
public:
    T m_key;
    U m_value;
    std::unique_ptr<Node<T,U>> pNode = nullptr; //内存是否能回收?
};

//基于hash table 实现的HashMap 冲突解决使用拉链法
template <typename T,typename U>
class HashMap{
public:
    explicit HashMap(const unsigned int size){
        this->m_size = size;
        m_ppNode = std::make_unique<unique_ptr<Node<T,U>>[]>(m_size);
        for(unsigned int index=0;index<m_size;index++){
            m_ppNode[index].reset(nullptr);
        }
    }
public:
    void Insert(const T& key,const U& value){
        int index = std::hash<T>{}(key)%m_size; //std::hash C++ 17
        std::unique_ptr<Node<T,U>> newNode = std::make_unique<Node<T,U>>(key,value);
        if(m_ppNode[index] == nullptr){
            m_ppNode[index] = std::move(newNode);//内存是否被正确回收?待验证
            return ;
        }
        //map容器考虑去重
        Node<T,U>* node = m_ppNode[index].get();
        while(node->pNode!= nullptr){
            if(node->m_key == key){
                node->m_value = value;
                return;
            }
            node = node->pNode.get();
        }
        if(node->m_key == key){ //判断循环最后一个元素
            node->m_value = value;
            return ;
        }
        //没有重复的元素 采用尾插法
        node->pNode = std::move(newNode);
    }

    pair<U,bool> Find(const T&key){
        int index = std::hash<T>{}(key)%m_size;
        auto p = m_ppNode[index].get();
        while(p!= nullptr){
            if(p->m_key == key){
                return make_pair(p->m_value, true);
            }
            p = p->pNode.get();
        }
        return make_pair(U(), false);
    }
private:
    std::unique_ptr<unique_ptr<Node<T,U>>[]> m_ppNode = nullptr;//unique_ptr对象数组
    unsigned int m_size=0;
};

int main() {
    {
        HashMap<string,string> map(100);
        map.Insert("a","aaa");
        map.Insert("b","bbb");

        pair<string,bool> ret1 = map.Find("a");
        if(ret1.second){
            std::cout<<"find:value="<<ret1.first<<std::endl;
        } else{
            std::cout<<"not find"<<std::endl;
        }

        pair<string,bool> ret2 = map.Find("b");
        if(ret2.second){
            std::cout<<"find:value="<<ret2.first<<std::endl;
        } else{
            std::cout<<"not find"<<std::endl;
        }

        pair<string,bool> ret3 = map.Find("c");
        if(ret3.second){
            std::cout<<"find:value="<<ret3.first<<std::endl;
        } else{
            std::cout<<"not find"<<std::endl;
        }
    }
    return 0;
}

HashMapのハッシュテーブルの単純な実装(リニアプローブ法、第二のプローブ法)に基づきます

参照だけのためのコード:GitHubのアドレス

#include <iostream>
#include <string>
#include <vector>

using namespace std;

enum State{
    EMPTY,
    DELETE,
    EXIST
};

//hash table 内部节点
template <typename K,typename V>
class HashNode{
public:
    HashNode():m_state(EMPTY){}
public:
    std::pair<K,V> m_kv;
    State m_state;
};

//基于hash table 实现的HashMap 冲突解决使用开放地址法
template <typename K,typename V,bool isLine = true> //模板偏特化
class HashMap{
public:
    explicit HashMap(const unsigned int size = 10):m_size(0){
        m_table.resize(GetNextPrime(size));
    }
public:
    bool Insert(const K& key,const V& value){
        CheckSize();
        unsigned int hashAddr = std::hash<K>{}(key)%m_table.size();//C++ 17
        unsigned int index = hashAddr;
        unsigned int i = 1;
        while(m_table[index].m_state == EXIST){
            if(m_table[index].m_kv.first == key){
                return false;
            }
            if(isLine){
                index = DetectedLine(index);
            }else{
                index = DetectedSquare(index,i++);
            }
        }
        m_table[index].m_kv = std::make_pair(key,value);
        m_table[index].m_state = EXIST;
        m_size++;
        return true;
    }

    std::pair<HashNode<K,V>*,bool> Find(const K&key){
        unsigned int hashAddr = std::hash<K>{}(key)%m_table.size();//C++ 17
        unsigned int index = hashAddr;
        HashNode<K, V>& elem = m_table[index];
        if(elem.m_kv.first!=key){ //产生冲突了 继续寻找
            if(isLine){//线性查找
                while(true){
                    index = DetectedLine(index);
                    if(index == hashAddr){
                        return std::make_pair(&elem,false);
                    }
                    if(m_table[index].m_kv.first == key && m_table[index].m_state == EXIST){
                        return std::make_pair(&m_table[index], true);
                    }
                }
            }else{//平方查找
                unsigned int i = 1;
                while(m_table[index].m_state != EMPTY){ //EXIST和DELETE都是要查找的目标
                    index = DetectedSquare(index,i++);
                    if(m_table[index].m_kv.first == key && m_table[index].m_state == EXIST){
                        return std::make_pair(&m_table[index], true);
                    }
                }
            }
        }else{
            if(m_table[index].m_state == EXIST){
                return make_pair(&elem, true);
            }
        }

        return make_pair(&elem, false);
    }

    bool Remove(const K& key){
        auto ret = Find(key);
        if(ret.second){
            ret.first->m_state = DELETE;
            m_size--;
            return true;
        }
        return false;
    }

    inline unsigned int Size(){
        return m_size;
    }

private:
    unsigned int DetectedLine(unsigned int hashAddr){ //线性探查法
        hashAddr++;
        if(hashAddr == m_table.size()){
            hashAddr = 0;
        }
        return hashAddr;
    }

    unsigned int DetectedSquare(unsigned int hashAddr, unsigned int i){//平方探查法
        /*
         * H(i) = H0 + i^2
         * H(i-1) = H0 + (i-1)^2
         * H(i) = H(i-1) + 2*i - 1 = H(i-1) + i<<1 - 1
         * */
        hashAddr = hashAddr + 2*i - 1;
        hashAddr = hashAddr % m_table.size() ;
        return hashAddr;
    }

    void CheckSize(){
        if(m_size/m_table.size()*10>=6){ //当装载因子a大于0.5时,需要将vector扩容处理
            m_table.resize(GetNextPrime(m_size));

            HashMap<K,V,isLine> hm;
            for(auto it : m_table){
                if(it.m_state == EXIST){
                    hm.Insert(it.m_kv.first,it.m_kv.second);
                }
            }
            this->Swap(hm);
        }
    }

    void Swap(HashMap<K,V,isLine> hm){
        std::swap(m_size,hm.m_size);
        m_table.swap(hm.m_table);
    }

    unsigned int GetNextPrime(const unsigned int size){//使用素数表对齐做哈希表的容量,降低哈希冲突
        const int _PrimeSize = 28;
        static const unsigned long _PrimeList[_PrimeSize] ={
                52ul, 97ul, 193ul, 389ul, 769ul,
                1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
                49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
                1572869ul, 3145739ul, 6291469ul, 12582917ul, 24165843ul,
                50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
                1610612741ul, 3221225473ul, 4294967291ul
        };

        for(unsigned i = 0; i < _PrimeSize; ++i){
            if (_PrimeList[i] > size){
                return _PrimeList[i];
            }
        }
        return _PrimeList[_PrimeSize-1];
    }

private:
    std::vector<HashNode<K,V>> m_table; //hash table
    unsigned int m_size=0;//hash table store element number
};

int main() {
    {
        HashMap<int,int,false> map;
        map.Insert(25, 1);
        map.Insert(25, 2);
        map.Insert(14, 2);
        map.Insert(36, 3);
        map.Insert(49, 4);
        map.Insert(68, 5);
        map.Insert(57, 6);
        map.Insert(11, 7);
        map.Insert(37, 8);

        cout<<map.Size()<<endl;

        auto ret = map.Find(25);
        if(ret.second){
            std::cout<<"Find:key="<<ret.first->m_kv.first<<" value="<<ret.first->m_kv.second<<std::endl;
        }else{
            std::cout<<"not find"<<std::endl;
        }

        ret = map.Find(11);
        if(ret.second){
            std::cout<<"Find:key="<<ret.first->m_kv.first<<" value="<<ret.first->m_kv.second<<std::endl;
        }else{
            std::cout<<"not find"<<std::endl;
        }

        ret = map.Find(12);
        if(ret.second){
            std::cout<<"Find:key="<<ret.first->m_kv.first<<" value="<<ret.first->m_kv.second<<std::endl;
        }else{
            std::cout<<"not find:12"<<std::endl;
        }

        map.Remove(25);
        ret = map.Find(25);
        if(ret.second){
            std::cout<<"Find:key="<<ret.first->m_kv.first<<" value="<<ret.first->m_kv.second<<std::endl;
        }else{
            std::cout<<"not find:25"<<std::endl;
        }

        map.Remove(14);
        cout<<map.Size()<<endl;
    }
    return 0;
}
公開された155元の記事 ウォン称賛15 ビュー160 000 +

おすすめ

転載: blog.csdn.net/wangdamingll/article/details/104198484