散列表(hash table):是表示集合和字典的另一种有效方法,它提供了一种完全不同的存储和搜索方式,通过将关键码映射到表中某个位置上来存储元素,然后根据关键码用同样的方式直接访问。
需要注意两点:
1.散列函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址时,其值域必须在0到m-1之间。
2.散列函数计算出来的地址应能均匀分布在整个地址空间中。
散列函数中用的最多的是除留余数法,m个地址,取一个不大于m但最接近m的素数p作为除数,
hash(key)=key%p,素数p不是接近2的幂

#ifndef HASHTABLE_H
#define HASHTABLE_H

const int DefaultSize=100;
enum KindOfStatus{
    Active,//有元素
    Empty,
    Deleted
};

template<typename E,typename K>
class HashTable{
public:
    HashTable(const int d,int sz=DefaultSize);
    ~HashTable(){
        delete []ht;
        delete []info;
    }
    HashTable<E,K>& operator=(const HashTable<E,K>& ht2);
    bool Search(const K k1,E& e1)const;
    bool Insert(const E& e1);
    bool Remove(const K k1,E& e1);
    void makeEmpty();
private:
    int divitor;//散列函数的除数
    int CurrentSize,TableSize;
    E *ht;//散列函数的存储数组
    KindOfStatus *info;
    int FindPos(const K k1)const;
    int operator==(E& e1){
        return *this==e1;
    }
    int operator!=(E& e1){
        return *this!=e1;
    }
};

template<typename E,typename K>
HashTable<E,K>::HashTable(int d,int s){
    divitor = d;
    TableSize = sz;
    CurrentSzie = 0;
    ht = new E[TableSize];
    info = new KindOfStatus[TableSize];
    for(int i=0;i<TableSize;i++)
        info[i]=Empty;
}

template<typename E,typename K>
int HashTable<E,K>::FindPos(const K k1) const
{
    int i = k1%divitor;
    int j = i;
    do{
        if(info[j]==Empty||info[j]==Active&&ht[j]==k1){
            return j;
        }else{
            j++;
        }
    }while(j!=i);
    return j;//表满
}

template<typename E,typename K>
bool HashTable<E,K>::Search(const K k1, E &e1) const
{
    int i = FindPos(k1);
    if(info[i]!=Active||ht[i]!=k1)
        return false;
    e1 = ht[i];
    return true;
}

template<typename E,typename K>
void HashTable<E,K>::makeEmpty()
{
    for(int i=0;i<TableSize;++i)
        info[i]=Empty;
    CurrentSize=0;
}

template<typename E,typename K>
HashTable<E,K>& HashTable<E,K>::operator=(const HashTable<E,K>& ht2)
{
    if(this!=&ht2){
        delete []ht;
        delete []info;
        TableSize = ht2.TableSize;
        ht = new E[TableSize];
        info = new KindOfStatus[TableSize];
        for(int i=0;i<TableSize;i++){sz
            ht[i] = ht2.ht[i];
            info[i] = ht2.info[i];
        }
        CurrentSize = ht2.CurrentSize;
    }
    return *this;
}

template<typename E,typename K>
bool HashTable<E,K>::Insert(const E &e1)
{
    K k1 = e1;
    int i = FindPos(k1);
    if(info[i]!=Active){
        ht[i] = e1;
        info[i] = Active;
        CurrentSize++;
        return true;
    }
    if(info[i]==Active&&ht[i]==e1){
        cout << "已存在些元素不能插入" << endl;
        return false;
    }
    cout << "表已满,不能插入" << endl;
    return false;
}

template<typename E,typename K>
bool HashTable<E,K>::Remove(const K k1, E &e1)
{
    int i = FindPos(k1);
    if(info[i]==Active&&ht[i]==e1){
        info[i]=Deleted;
        CurrentSize--;
        return true;
    }
    return false;
}

#endif // HASHTABLE_H