c++ unordered_map 源码的解析以及vector,string实现

本文详细解析了C++标准库中unordered_map的数据结构实现原理,探讨了哈希冲突的处理方式,以及如何通过自定义HashFunc进行优化。作者还提供了基于哈希表的简单HashMap实现示例,适合初学者研究内存映射哈希表的内部机制。
摘要由CSDN通过智能技术生成

https://blog.csdn.net/yangxuan0261/article/details/52090128

深入剖析 std::unordered_map 的实现原理之 Hash冲突、退化

c++ 实现hashmap - myd620 - 博客园 (cnblogs.com)   好文章

// gnu 实现
  template<typename _Key, 
           typename _Tp,
           typename _Hash  = hash<_Key>,
           typename _Pred  = equal_to<_Key>,
           typename _Alloc = allocator<std::pair<const _Key, _Tp>>>
    class unordered_map
    {
      typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc>  _Hashtable;
      _Hashtable _M_h; 	// 内部的唯一成员变量: hashtable
     //...   
    }

c++ vector的底层实现

c++简单String类实现

最终实现unordered_map的代码:

#include<bits/stdc++.h>
using namespace std;

template<class Key, class Value>
class HashNode{
    public:
    Key _key;
    Value _value;
    HashNode* next;

    HashNode(Key key, Value value)
    {
        _key=key;
        _value=value;
        next=NULL;
    }
    ~HashNode()
    {
        
    }
};

template<class Key, class Value, class HashFunc>
class HashMap
{
    public:
    HashMap(int size);
    ~HashMap();
    void insert(const Key& key, const Value& value);
    bool del(const Key& key);
    Value& find(const Key& key);
    Value& operator [](const Key& key);

    private:
    HashFunc hash;
    HashNode<Key, Value> **table;//因为是数组,所以两个*,一个*代表指针数组
    int _size;
    Value valueNull;
};

template<class Key, class Value, class HashFunc>
HashMap<Key, Value, HashFunc>::HashMap(int size):_size(size)
{
    table=new HashNode<Key, Value>* [size];
    for(int i=0; i<size; i++){
        table[i] = NULL;
    }
}

template<class Key, class Value, class HashFunc>
HashMap<Key, Value, HashFunc>::~HashMap()
{
    for(int i=0; i<_size; i++){
        HashNode<Key, Value>* node = table[i];
        while(node){
            HashNode<Key, Value> *tmp=node;
            node = node->next;
            delete tmp;
        }
    }
    delete table;
}

template<class Key, class Value, class HashFunc>
void HashMap<Key, Value, HashFunc>::insert(const Key& key, const Value& value)
{
    int index = hash(key)%_size;
    HashNode<Key, Value> *node = table[index];
    while(node){
        if(node->_key == key){
            return;//insert以第一次插入的value为准
        }
        node = node->next;
    }
    node = new HashNode<Key, Value>(key, value);
    node->next=table[index];
    table[index]=node;
}

template<class Key, class Value, class HashFunc>
Value& HashMap<Key, Value, HashFunc>::find(const Key &key)
{
    int index = hash(key) % _size;
    HashNode<Key, Value> *node = table[index];
    while(node){
        if(node->_key == key){
            return node->_value;
        }
        node = node->next;
    }
    node = new HashNode<Key, Value>(key,valueNull);
    node->next = table[index];
    table[index] = node;
    return table[index]->_value;
}


template<class Key, class Value, class HashFunc>
Value& HashMap<Key, Value, HashFunc>::operator[](const Key& key)
{
    return find(key);
}

template<class Key, class Value, class HashFunc>
bool HashMap<Key, Value, HashFunc>::del(const Key& key)
{
    int index = hash(key) % _size;
    HashNode<Key, Value> *node = table[index];
    HashNode<Key, Value> *preNode = NULL;
    while(node){
        if(node->_key == key){
            if(preNode == NULL){
                table[index] = node->next;
            }
            else{
                preNode->next = node->next;
            }
            delete node;
            return true;
        }
        else{
            preNode = node;
            node = node->next;
        }
    }
    return false;
}

class HashFunc
{
    public:
    int operator()(const string& key)
    {
        int hash=0;
        for(int i = 0; i < key.size(); i++){
            hash=hash<<7^key[i];
        }
        return (hash&0x7fffffff);
    }
};

int main()
{
    HashMap<string, string, HashFunc> hashmap(10);
    hashmap.insert("aaaa","1111");
    hashmap.insert("bbbb","2222");

    cout<<"after insert:"<<endl;
    cout<<hashmap.find("aaaa")<<endl;
    cout<<hashmap.find("bbbb")<<endl;

    if(hashmap.del("aaaa")){
        cout<<"remove is ok!"<<endl;
    }
    cout<<hashmap.find("aaaa")<<endl;

    hashmap["cccc"]="3333";
    hashmap["dddd"]="4444";
    cout<<"after = assign:"<<endl;
    cout<<hashmap["cccc"]<<endl;
    cout<<hashmap.find("dddd")<<endl;
    return 0;
}

最初版代码:

#include<bits/stdc++.h>
using namespace std;

template<class Key, class Value>
class HashNode
{
public:
    Key    _key;
    Value  _value;
    HashNode *next;

    HashNode(Key key, Value value)
    {
        _key = key;
        _value = value;
        next = NULL;
    }
    ~HashNode()
    {

    }
    /*HashNode& operator=(const HashNode& node)
    {
        _key  = node._key;
        _value = node._value;
        next = node.next;
        return *this;
    }*/
};

template <class Key, class Value, class HashFunc>
class HashMap
{
public:
    HashMap(int size);
    ~HashMap();
    bool insert(const Key& key, const Value& value);
    bool del(const Key& key);
    Value& find(const Key& key);
    Value& operator [](const Key& key);

private:
    HashFunc hash;
    //EqualKey equal;
    HashNode<Key, Value> **table;
    unsigned int _size;
    Value ValueNULL;
};


template <class Key, class Value, class HashFunc>
HashMap<Key, Value, HashFunc>::HashMap(int size) : _size(size),hash()
{
    table = new HashNode<Key, Value>*[_size];
    for (unsigned i = 0; i < _size; i++)
        table[i] = NULL;
}



template <class Key, class Value, class HashFunc>
HashMap<Key, Value, HashFunc>::~HashMap()
{
    for (unsigned i = 0; i < _size; i++)
    {
        HashNode<Key, Value> *currentNode = table[i];
        while (currentNode)
        {
            HashNode<Key, Value> *temp = currentNode;
            currentNode = currentNode->next;
            delete temp;
        }
    }
    delete table;
}


template <class Key, class Value, class HashFunc>
bool HashMap<Key, Value, HashFunc>::insert(const Key& key, const Value& value)
{
    int index = hash(key)%_size;
    HashNode<Key, Value> * node = new HashNode<Key, Value>(key,value);
    node->next = table[index];
    table[index] = node;
    return true;
}


template <class Key, class Value, class HashFunc>
bool HashMap<Key, Value, HashFunc>::del(const Key& key)
{
    unsigned index = hash(key) % _size;
    HashNode<Key, Value> * node = table[index];
    HashNode<Key, Value> * prev = NULL;
    while (node)
    {
        if (node->_key == key)
        {
            if (prev == NULL)
            {
                table[index] = node->next;
            }
            else
            {
                prev->next = node->next;
            }
            delete node;
            return true;
        }
        prev = node;
        node = node->next;
    }
    return false;
}

template <class Key, class Value, class HashFunc>
Value& HashMap<Key, Value, HashFunc>::find(const Key& key)
{
    unsigned  index = hash(key) % _size;
    if (table[index] == NULL)
    {
        HashNode<Key, Value> * node = new HashNode<Key, Value>(key,ValueNULL);
        node->next = table[index];
        table[index] = node;
        //cout<<"---2"<<endl;
        return table[index]->_value;
    }
    else
    {
        HashNode<Key, Value> * node = table[index];
        while (node)
        {
            if (node->_key == key)
                return node->_value;
            node = node->next;
        }
    }
}


template <class Key, class Value, class HashFunc>
Value& HashMap<Key, Value, HashFunc>::operator [](const Key& key)
{
    //cout<<"---1"<<endl;
    return find(key);
}


class HashFunc
{
public:
    int operator()(const string & key )
    {
        int hash = 0;
        for(int i = 0; i < key.length(); ++i)
        {
            hash = hash << 7 ^ key[i];
        }
        return (hash & 0x7FFFFFFF);
    }
};


class EqualKey
{
public:
    bool operator()(const string & A, const string & B)
    {
        if (A.compare(B) == 0)
            return true;
        else
            return false;
    }
};

int main()
{
    HashMap<string, string, HashFunc> hashmap(100);

    hashmap.insert("hello", "world");
    hashmap.insert("why", "dream");
    hashmap.insert("c++", "good");
    hashmap.insert("welcome", "haha");


    cout << "after insert:" << endl;
    cout << hashmap.find("welcome").c_str() << endl;
    cout << hashmap.find("c++").c_str() << endl;
    cout << hashmap["why"].c_str() << endl;
    cout << hashmap["hello"].c_str() << endl;

    if (hashmap.del("hello"))
        cout << "remove is ok" << endl;    //remove is ok
    cout << hashmap.find("hello").c_str() << endl; //not exist print NULL

    hashmap["what"] = "love";
    cout << hashmap["what"].c_str() << endl;

    hashmap["where"] = "beijing";
    cout << hashmap["where"].c_str() << endl;
    cout<<"------"<<hashmap["you"]<<endl;
    cout<<"#######"<<hashmap["what"]<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值