// ConsoleTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <string> const int primes[] = {2009,3009,4009,5009,6009,7009,8009,16009}; template<class T> int hash(T t){return t.hashCode();} template <class KeyT,class ValT> struct MyPair { typedef KeyT TypeKey; typedef ValT TypeVal; KeyT key; ValT value; }; template <class Pair> struct BucketNode { typedef Pair DataType; Pair PairValue; BucketNode* pNext; }; template <class DataType> struct Bucket { typedef DataType Pair ; typedef BucketNode<Pair> NodeType; BucketNode<Pair>* pHead; }; template<class Bucket> class HashMap { public: typedef typename Bucket::Pair MapPairType; typedef typename MapPairType::TypeKey KeyT; typedef typename MapPairType::TypeVal ValT; HashMap(); const typename MapPairType* GetValue(KeyT key); void insert(MapPairType data); void rehash(); unsigned int HashValue(unsigned int hashCode); float fHashFacil; int nContOfContent; int indexCapbility; Bucket** pContent; }; template<class Bucket> const typename HashMap<Bucket>::MapPairType* HashMap<Bucket>::GetValue(KeyT key) { int indexOfFind = HashValue(hash(key)); Bucket::NodeType* pNode = pContent[indexOfFind]->pHead; while (pNode != NULL) { if (pNode->PairValue.key == key) { return &(pNode->PairValue); } else { pNode = pNode->pNext; } } return NULL; } template<class Bucket> void HashMap<Bucket>::rehash() { Bucket** oldContent = pContent; int oldIndexCapbility = indexCapbility; if (indexCapbility >= sizeof(primes)/sizeof(primes[0]) - 1) { return; } while ((int)(fHashFacil*primes[indexCapbility]) < nContOfContent) { if (indexCapbility >= sizeof(primes)/sizeof(primes[0]) - 1) { break; } indexCapbility ++; } // //Rehash the table. // //Reset the Count to zero. nContOfContent = 0; //Insert old data to new table; pContent = new Bucket* [primes[indexCapbility]]; memset(pContent, 0, primes[indexCapbility]*sizeof(Bucket*)); for (int i = 0; i<primes[oldIndexCapbility]; i ++) { if (oldContent[i] != NULL) { Bucket::NodeType* pNode = oldContent[i]->pHead; while (pNode) { insert(pNode->PairValue); Bucket::NodeType* oldNode = pNode; pNode = pNode->pNext; delete oldNode; } } } delete[] oldContent; } template<class Bucket> void HashMap<Bucket>::insert(MapPairType data) { if ((int)(fHashFacil*primes[indexCapbility]) < nContOfContent) { //std::cout<<"The current conten is "<<mapHash.nContOfContent<<std::endl; std::cout<<"Rehash:The current capbility is"<<primes[indexCapbility]<<std::endl; std::cout<<"Rehash:The current count is"<<nContOfContent<<std::endl; rehash(); } int hashVal = HashValue(hash(data.key)); std::cout<<hashVal<<"\t"<<data.key.m_strValue.data()<<"\t"<<data.value<<std::endl; if (pContent[hashVal] == NULL) { Bucket* pBucket = new Bucket; pBucket->pHead = new Bucket::NodeType; pBucket->pHead->PairValue = data; pBucket->pHead->pNext = NULL; pContent[hashVal] = pBucket; //delete pBucket; } else { Bucket::NodeType* pNode = pContent[hashVal]->pHead; while (pNode->pNext!= NULL) { pNode = pNode->pNext; } Bucket* pBucket = new Bucket; pNode->pNext = new Bucket::NodeType; pNode->pNext->pNext = NULL; pNode->pNext->PairValue = data; } nContOfContent ++; } template<class Bucket> HashMap<Bucket>::HashMap() { fHashFacil = 0.75; indexCapbility = 0; nContOfContent = 0; pContent = NULL; pContent = new Bucket* [primes[indexCapbility]]; memset(pContent, 0, primes[indexCapbility]*sizeof(Bucket*)); } template<class Bucket> unsigned int HashMap<Bucket>::HashValue(unsigned int hashCode) { return hashCode%(primes[indexCapbility]); } //下面是测试程序。 //作为hashmap的(key,value)对中key必须定义==操作符和HashCode方法。 class HashString { friend bool operator== (const HashString& keyLeft, const HashString& keyRight); public: HashString(const std::string& strValue) { m_strValue = strValue; } HashString() { m_strValue = (""); } operator std::string() { return m_strValue; } int hashCode() { register unsigned int h; register unsigned char *p; for(h=0, p = (unsigned char *)m_strValue.data(); *p ; p++) h = 31 * h + *p; return h; } std::string m_strValue; }; bool operator== (const HashString& keyLeft, const HashString& keyRight) { return keyLeft.m_strValue == keyRight.m_strValue; } int _tmain(int argc, _TCHAR* argv[]) { HashMap<Bucket<MyPair<HashString, unsigned int>>> mapHash; for(int i = 0; i< 1000; i++) { MyPair<HashString, unsigned int> pairValue1; std::string strValue("XiongBei"); char buffer[33]; _itoa_s(i,buffer,33,10); pairValue1.key = strValue.append(buffer); pairValue1.value = i; mapHash.insert(pairValue1); } //std::cout<<"The current conten is "<<mapHash.nContOfContent<<std::endl; std::cout<<"The current capbility is"<<primes[mapHash.indexCapbility]<<std::endl; std::cout<<"The current count is"<<mapHash.nContOfContent<<std::endl; return 0; }
08-17