【数据结构】哈希表(2)

哈希表的讲解:
https://blog.csdn.net/lz201788/article/details/79735508

以下是哈希表的另外的实现方式:

【1.】(不使用vector)

【HashTable2.h】

#pragma once
#include<iostream>
#include<string>
using namespace std;

#define CAPACITY 11

enum Status
{
    EXIST,
    DELETE,
    EMPTY
};
template<class K,class V>
struct HashNode
{
    HashNode(K key=K(),V value=V())
    :_key(key)
    , _value(value)
    , _status(EMPTY)
    {}

    K _key;
    V _value;
    Status _status;
};

//定义仿函数
template<class K>
struct _HashFunc
{
    size_t operator()(const K& key)
    {
        return key;
    }
};

//特化string的版本
template<>
struct _HashFunc<string>
{
    static size_t BKDHash(const char* str)
    {
        size_t seed = 131;   //13 131 1313 13131
        size_t hash = 0;
        while (*str)
        {
            hash = hash*seed + (*str);
            str++;
        }
        return (hash & 0x7fffffff);
    }
    size_t operator()(const string&key)
    {
        return BKDHash(key.c_str());   //c_str() 返回的是一个const char* 类型的字符串
    }
};

//素数表,表内为哈希表的容量,素数降低哈希冲突
const int _PrimeSize = 28;
static const unsigned long _PrimeList[_PrimeSize] =
{
    53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul,
    12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul,
    786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul,
    25165843ul, 50331653ul, 100663319ul, 201326611ul,
    402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
    4294967291ul
};


template<class K,class V,class HashFunc=_HashFunc<K>>
class HashTable
{
    typedef HashNode<K, V> Node;

public:

    HashTable(const size_t& capacity=11)
        :_size(0)
        , _capacity(capacity)
    {
        head = new Node[capacity];
    }

    bool Insert(const K& key,const V& value)
    {
        //检查是否需要扩容
        CheckCapacity();
        //对key值进行取余判断插入位置
        size_t index = HashTableFunc(key);
        //如果存在则循环着继续找

        //LineCheck(index);     //(1)线性探测

        SecondCheck(index);     //(2)二次探测


        head[index]._key = key;
        head[index]._value = value;
        head[index]._status = EXIST;

        _size++;
        return true;
    }

    int Find(const K& key)   //查找元素
    {
       //先求哈希值
        int index=HashTableFunc(key);
        int count = _capacity;
        while (count--)
        {
            if (head[index]._key == key)
                return index;
            index++;
            if (index == _capacity)
                index = 0;
        }
        return -1;    //没找到
    }

    bool Delete(const K& key)
    {
        int index = Find(key);
        if (index >= 0)
        {
            head[index]._status = DELETE;
            return true;
        }
        return false;
    }

    size_t Size()const
    {
        return _size;
    }

    bool Empty()const
    {
        return _size == 0;
    }

    ~HashTable()
    {
        if (head != NULL)
            delete[]head;
        _size = 0;
        _capacity = 0;
    }

    void Display()
    {
        for (size_t i = 0; i < _capacity; i++)
        {
            cout <<i<<":"<< head[i]._key << "-->" << head[i]._value << endl;
        }
    }
private:
    int HashTableFunc(const K& key)
    {
        HashFunc hf;          //定义一个_HashFunc<K> 的对象hf
        size_t hash = hf(key);       //用hf调用相应的仿函数,返回一个整型
        return (hash%_capacity);  //算出哈希值并返回
    }

    void LineCheck(size_t& index)     //线性探测
    {
        while (head[index]._status != EMPTY)
        {
            index++;
            if (index == _capacity)
                index = 0;
        }
    }

    void SecondCheck(size_t& index)    //二次探测
    {
        int num = 0;
        int ret = index;
        while (head[index]._status != EMPTY)
        {
            num++;
            index = ret+ num*num;
        }
    }

    void CheckCapacity()        //扩容函数
    {
        //如果超过比例系数就需要扩容
        if ((_size * 10) / _capacity >= 7)
        {
            int index = 0;
            while (index<_PrimeSize)
            {
                if (_PrimeList[index] < _capacity)
                    index++;
                else
                {
                    HashTable<K, V> newHash(_PrimeList[index]);
                    for (size_t i = 0; i < _capacity; i++)
                    {
                        if (head[i]._status==EXIST)
                        newHash.Insert(head[i]._key, head[i]._value);
                    }
                    Swap(newHash);
                    break;
                }
            }
        }
    }

    void Swap(HashTable<K, V>& newHash)
    {
        swap(head,newHash.head);
        swap(_size,newHash._size);
        swap(_capacity, newHash._capacity);
    }

private:
    Node* head;
    size_t _size;
    size_t _capacity;
};

void test3()   //测试整型
{
    int arr[] = {12,3,24,14,25,10,19,78,30,35};
    int size = sizeof(arr) / sizeof(arr[0]);
    HashTable<int, int> h1;
    for (int i = 0; i < size; i++)
    {
        h1.Insert(arr[i], arr[i] + 3);
    }
    h1.Display();
} 
void charTest()   //测试字符型
{
    HashTable<string, string> h2;
    h2.Insert("1111","1111");
    h2.Insert("1112", "1112");
    h2.Insert("1113", "1113");
    h2.Insert("1114", "1114");
    h2.Insert("1115", "1115");
    h2.Display();
}

【test.cpp】

#include"HashTable2.h"

int main()
{
    //test();
    //test2();
    //test3();
    charTest();

    system("pause");
    return 0;
}


【2.】哈希表(开散列)加迭代器
【HashIterator.h】

#pragma once
#include<iostream>
#include<vector>
#include<string>
#include<windows.h>
using namespace std;

//定义仿函数
template<class K>
struct _HashFunc
{
    size_t operator()(const K& key)
    {
        return key;
    }
};

//特化string版本
template<>             
struct _HashFunc<string>
{
    static size_t BDKHash(const char* str)
    {
        size_t seed = 131;   //13 131 1313 13131 .....
        size_t hash = 0;
        while (*str)
        {
            hash = hash*seed + (*str);
            str++;
        }
        return (hash & 0x7fffffff);
    }
    size_t operator()(const string& key)
    {  
        return BDKHash(key.c_str());  //返回一个const char* 类型的字符串
    }

};

template<class K,class V>
struct HashNode
{
    HashNode(const K& key=K(),const V& value=V())
    :Next(NULL)
    , _key(key)
    , _value(value)
    { }

    struct HashNode* Next;
    K _key;
    V _value;

};

//素数表,表内为哈希表的容量,素数降低哈希冲突
const int _PrimeSize = 28;
static const unsigned long _PrimeList[_PrimeSize] =
{
    53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul,
    12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul,
    786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul,
    25165843ul, 50331653ul, 100663319ul, 201326611ul,
    402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
    4294967291ul
};

template<class K, class V, class HashFunc = _HashFunc<K>>
class HashTable;

//迭代器
template<class K, class V>
struct HashIterator
{

    typedef HashIterator<K, V> Iter;
    typedef HashNode<K, V>* pNode;
    typedef HashTable<K, V> HashTable;

    HashIterator()
        :_pHead(NULL)
        , _ht(NULL)
    {}
    HashIterator(pNode _Node, HashTable* ht)
        :_pHead(_Node)
        , _ht(ht)
    { }
    Iter& operator++()
    {
        _pHead = _Next(_pHead);
        return (*this);
    }
    Iter operator++(int)
    {
        Iter ret(*this);
        ++(*this);
        return ret;
    }

    K operator*()
    {
        return _pHead->_key;
    }
    pNode operator->()
    {
        return _pHead;
    }
    bool operator!=(Iter& s)
    {
        return _pHead != s._pHead;
    }
    bool operator==(Iter& s)
    {
        return _pHead == s._pHead;
    }
private:
    pNode _Next(pNode& _node)
    {
        pNode temp = _node->Next;
        if (temp)
        {
            return temp;
        }
        else
        {
            int index = _ht->HashTableFunc(_pHead->_key)+1;
            for (size_t i = index; i < _ht->Capacity(); i++)
            {
                pNode ret = _ht->_hash[i];
                if (ret)
                {
                    return ret;
                }
            }
            return NULL;
        }
    }

private:
    pNode _pHead;
    HashTable* _ht;
};


template<class K,class V,class HashFunc>
class HashTable
{
    typedef HashNode<K, V> Node;
    friend struct HashIterator<K, V>;
    typedef HashIterator<K, V> Iterator;
public:
    HashTable(const size_t& capacity=11)
    { 
        _size = 0;
        _hash.resize(capacity);
    }

    //key可重复插入
    bool InsertEqual(const K& key,const V& value)
    {
        //检测是否需要扩容
        CheckCapacity();
        //求哈希值
        size_t index = HashTableFunc(key);
        if (_hash[index] == NULL)
        {
            _hash[index] = new Node(key, value);
            _size++;
            return true;
        }

        Node*ret = _hash[index];
        Node*cur = NULL;
        while (ret)
        {
            cur = ret;
            ret = ret->Next;
        }
        Node* newNode = new Node(key, value);
        cur->Next = newNode;
        _size++;
        return true;
    }

    //key不能重复的插入
    bool InsertUnique(const K& key,const V& value)
    {
        //检测是否需要扩容
        CheckCapacity();
        //求哈希值
        size_t index = HashTableFunc(key);
        if (_hash[index] == NULL)
        {
            _hash[index] = new Node(key, value);
            _size++;
            return true;
        }

        Node*ret = _hash[index];
        Node*cur = NULL;
        while (ret)
        {
            cur = ret;
            if (ret->_key == key)
                return false;
            ret = ret->Next;
        }
        Node* newNode = new Node(key, value);
        cur->Next = newNode;
        _size++;
        return true;
    }

    //删除有重复元素
    bool DeleteEqual(const K& key)
    {
        size_t index = HashTableFunc(key);
        Node* ret = _hash[index];

        if (ret == NULL)
            return false;

        Node* cur = NULL;
        while (ret)
        {
            if (ret->_key == key)
            {

                if (ret == _hash[index])
                {
                    _hash[index] = ret->Next;
                    delete ret;
                    _size--;
                    ret = _hash[index];
                }
                else
                {
                    cur->Next = ret->Next;
                    delete ret;
                    _size--;
                    ret = cur->Next;
                }
            }
            else
            {
                cur = ret;
                ret = ret->Next;
            }
        }
        return true;
    }

    //删除无重复元素
    bool DeleteUnique(const K& key)
    {
        size_t index = HashTableFunc(key);
        Node* ret = _hash[index];

        Node* cur = NULL;
        while (ret)
        {
            if (ret->_key == key)
            {
                if (ret == _hash[index])
                {
                    _hash[index] = ret->Next;
                    delete ret;
                }
                else
                {
                    cur->Next = ret->Next;
                    delete ret;
                }
                _size--;
                ret = NULL;
                return true;
            }
                cur = ret;
                ret = ret->Next;
        }
        return false;

    }

    //迭代器
    Iterator Begin()   //返回第一个元素所在的位置
    {
        for (size_t i = 0; i < _hash.size(); i++)
        {
            if (_hash[i])
            {
                return Iterator(_hash[i],this);
            }
        }
        return Iterator(NULL, NULL);
    }

    Iterator End()
    {
        return Iterator(NULL,NULL);
    }

    bool Empty()
    {
        return (_size==0)
    }
    size_t Size()
    {
        return _size;
    }
    size_t Capacity()
    {
        return _hash.size();
    }

    size_t HashTableFunc(const K& key)    //求哈希值
    {
        HashFunc ht;   //定义一个_HashFunc<K>变量
        size_t hash = ht(key);
        return (hash%_hash.size());   
    }

    void Display() //打印函数
    {
        Iterator it = Begin();
        while (it != End())
        {
            //Sleep(1000);
            cout <<it->_key <<"-->"<<it->_value<<endl;
            it++;
        }
    }

    ~HashTable()
    {
        Clear();
    }

private:
    void Clear()  //清除函数
    {
        size_t count = _hash.size();
        for (size_t i = 0; i < count; i++)
        {
            if (_hash[i])
            {
                Node* ret = _hash[i];
                Node* cur = NULL;
                while (ret)
                {
                    _hash[i] = ret->Next;
                    delete ret;
                    ret = _hash[i];
                }
            }
        }
        _size = 0;
    }

    void CheckCapacity()          //扩容
    {
        if (_hash.size() == _size)
        {
            int newSize = 0;
            int index = 0;
            while (index < _PrimeSize)
            {
                if (_hash.size() < _PrimeList[index])
                {
                    newSize = index;
                    HashTable<K, V> newHash(newSize);
                    size_t count = 0;
                    while (count < _hash.size())
                    {
                        Node* ret = _hash[count];
                        while (ret)
                        {
                            newHash.InsertEqual(ret->_key, ret->_value);
                            ret = ret->Next;
                        }
                        count++;
                    }
                    Swap(newHash);
                }
                index++;
            }
        }
    }

    void Swap(HashTable<K,V>& newHash)    //交换地址
    {
        swap(_hash,newHash._hash);
        swap(_size,newHash._size);
    }

private:
    vector<Node*> _hash;
    size_t _size;
};
////////////////////////////////////测试函数
void test4()
{
    int arr[] = {2,13,12,34,56,23,45};
    int size = sizeof(arr) / sizeof(arr[0]);
    HashTable<int, int> h1;
    for (int i = 0; i < size; i++)
    {
        h1.InsertUnique(arr[i],arr[i]+3);
    }
    h1.Display();

}
void testchar4()   //key值插入不能重复
{
    HashTable<string, string> h2;

    h2.InsertUnique("abc", "abc");
    h2.InsertUnique("sed", "sed");
    h2.InsertUnique("hello", "hello");
    h2.InsertUnique("1111","1111");
    h2.InsertUnique("1112","2222");
    h2.InsertUnique("1113","3333");

    /*h2.DeleteUnique("1111");
    h2.DeleteUnique("hello");*/
    h2.Display();
}

void Equaltest()
{
    HashTable<string, string> h3;
    h3.InsertEqual("1111","1111");
    h3.InsertEqual("2222", "2222");
    h3.InsertEqual("1111", "3333");
    h3.InsertEqual("abc", "bsahd");
    h3.InsertEqual("abc", "5555");
    h3.DeleteEqual("abc");
    h3.DeleteEqual("1111");
}

【test.cpp】

#include"HashIterator.h"

int main()
{
    //test();
    //test2();
    //test3();
    //charTest();
    //test4();
    testchar4();
    //Equaltest();

    system("pause");
    return 0;
}

运行结果
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/lz201788/article/details/79774379