///////////////////////////////////////////////////////////////////////////// // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> class CMap : public CObject { public: // CPair struct CPair { const KEY key; VALUE value; protected: CPair( ARG_KEY keyval ) : key( keyval ) {} }; protected: // Association class CAssoc : public CPair { friend class CMap<KEY,ARG_KEY,VALUE,ARG_VALUE>; CAssoc* pNext; UINT nHashValue; // needed for efficient iteration public: CAssoc( ARG_KEY key ) : CPair( key ) {} }; public: // Construction /* explicit */ CMap(INT_PTR nBlockSize = 10); // Attributes // number of elements INT_PTR GetCount() const; // return m_nCount; INT_PTR GetSize() const; // return m_nCount; BOOL IsEmpty() const; // return m_nCount == 0; // Lookup BOOL Lookup(ARG_KEY key, VALUE& rValue) const; const CPair *PLookup(ARG_KEY key) const; CPair *PLookup(ARG_KEY key); // Operations // Lookup and add if not there VALUE& operator[](ARG_KEY key); // add a new (key, value) pair void SetAt(ARG_KEY key, ARG_VALUE newValue); // (*this)[key] = newValue; // removing existing (key, ?) pair BOOL RemoveKey(ARG_KEY key); void RemoveAll(); // iterating all (key, value) pairs POSITION GetStartPosition() const; // return (m_nCount == 0) ? NULL : BEFORE_START_POSITION; const CPair *PGetFirstAssoc() const; CPair *PGetFirstAssoc(); void GetNextAssoc(POSITION& rNextPosition, KEY& rKey, VALUE& rValue) const; const CPair *PGetNextAssoc(const CPair *pAssocRet) const; CPair *PGetNextAssoc(const CPair *pAssocRet); // advanced features for derived classes UINT GetHashTableSize() const; // return m_nHashTableSize; void InitHashTable(UINT hashSize, BOOL bAllocNow = TRUE); // Implementation protected: CAssoc** m_pHashTable; // Hash表 UINT m_nHashTableSize; // Hash表大小 INT_PTR m_nCount; // 元素数量 CAssoc* m_pFreeList; // 空闲节点链表 struct CPlex* m_pBlocks; // 数据块载体链表 INT_PTR m_nBlockSize; // 数据块大小 CAssoc* NewAssoc(ARG_KEY key); void FreeAssoc(CAssoc*); CAssoc* GetAssocAt(ARG_KEY, UINT&, UINT&) const; public: ~CMap(); void Serialize(CArchive&); #ifdef _DEBUG void Dump(CDumpContext&) const; void AssertValid() const; #endif };
InitHashTable 初始化Hash表
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::InitHashTable( UINT nHashSize, BOOL bAllocNow) // // Used to force allocation of a hash table or to override the default // hash table size of (which is fairly small) { if (m_pHashTable != NULL) { // free hash table delete[] m_pHashTable; m_pHashTable = NULL; } if (bAllocNow) { m_pHashTable = new CAssoc* [nHashSize]; memset(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize); } m_nHashTableSize = nHashSize; }
Lookup 查找key对应的元素值,查找成功则rValue中即为需要的值,同时返回TRUE。
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Lookup(ARG_KEY key, VALUE& rValue) const { UINT nHashBucket, nHashValue; CAssoc* pAssoc = GetAssocAt(key, nHashBucket, nHashValue); if (pAssoc == NULL) return FALSE; // not in map rValue = pAssoc->value; return TRUE; } // 获取键key对应的CAssoc结构指针,如果存在,nHashBucket返回其在Hash表中下标,nHashValue为键key的Hash值 template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc* CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAssocAt(ARG_KEY key, UINT& nHashBucket, UINT& nHashValue) const // find association (or return NULL) { nHashValue = HashKey<ARG_KEY>(key); // 可以覆盖,实现自己的Hash算法 nHashBucket = nHashValue % m_nHashTableSize; if (m_pHashTable == NULL) return NULL; // see if it exists CAssoc* pAssoc; for (pAssoc = m_pHashTable[nHashBucket]; pAssoc != NULL; pAssoc = pAssoc->pNext) { if (pAssoc->nHashValue == nHashValue && CompareElements(&pAssoc->key, &key)) return pAssoc; } return NULL; }
PLookup 查找key对应的Pair对。
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CPair* CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::PLookup(ARG_KEY key) { UINT nHashBucket, nHashValue; CAssoc* pAssoc = GetAssocAt(key, nHashBucket, nHashValue); return pAssoc; }
[] 操作符重载
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> VALUE& CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::operator[](ARG_KEY key) { UINT nHashBucket, nHashValue; CAssoc* pAssoc; if ((pAssoc = GetAssocAt(key, nHashBucket, nHashValue)) == NULL) { if (m_pHashTable == NULL) InitHashTable(m_nHashTableSize); // it doesn't exist, add a new Association pAssoc = NewAssoc(key); pAssoc->nHashValue = nHashValue; //'pAssoc->value' is a constructed object, nothing more // put into hash table pAssoc->pNext = m_pHashTable[nHashBucket]; m_pHashTable[nHashBucket] = pAssoc; } return pAssoc->value; // return new reference }
RemoveKey 移除key指定的元素
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveKey(ARG_KEY key) // remove key - return TRUE if removed { if (m_pHashTable == NULL) return FALSE; // nothing in the table UINT nHashValue; CAssoc** ppAssocPrev; nHashValue = HashKey<ARG_KEY>(key); ppAssocPrev = &m_pHashTable[nHashValue%m_nHashTableSize]; CAssoc* pAssoc; for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext) { if ((pAssoc->nHashValue == nHashValue) && CompareElements(&pAssoc->key, &key)) { // remove it *ppAssocPrev = pAssoc->pNext; // remove from list FreeAssoc(pAssoc); return TRUE; } ppAssocPrev = &pAssoc->pNext; } return FALSE; // not found }
RemoveAll 移除所有元素
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveAll() { if (m_pHashTable != NULL) { // destroy elements (values and keys) for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++) { CAssoc* pAssoc; for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext) { pAssoc->CAssoc::~CAssoc(); } } } // free hash table delete[] m_pHashTable; m_pHashTable = NULL; m_nCount = 0; m_pFreeList = NULL; m_pBlocks->FreeDataChain(); m_pBlocks = NULL; }
PGetFirstAssoc 获取第一个Assoc结构的指针
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CPair* CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::PGetFirstAssoc() { if(m_nCount == 0) return NULL; CAssoc* pAssocRet = (CAssoc*)BEFORE_START_POSITION; // find the first association for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++) if ((pAssocRet = m_pHashTable[nBucket]) != NULL) break; return pAssocRet; }
GetNextAssoc 获取rNextPosition所指元素的下一个元素的CAssoc指针,同时更新rNextPosition,并用rKey,rValue返回当前元素对应的值。
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetNextAssoc(POSITION& rNextPosition, KEY& rKey, VALUE& rValue) const { CAssoc* pAssocRet = (CAssoc*)rNextPosition; if (pAssocRet == (CAssoc*) BEFORE_START_POSITION) { // find the first association for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++) { if ((pAssocRet = m_pHashTable[nBucket]) != NULL) { break; } } } // find next association CAssoc* pAssocNext; if ((pAssocNext = pAssocRet->pNext) == NULL) { // go to next bucket for (UINT nBucket = (pAssocRet->nHashValue % m_nHashTableSize) + 1; nBucket < m_nHashTableSize; nBucket++) if ((pAssocNext = m_pHashTable[nBucket]) != NULL) break; } rNextPosition = (POSITION) pAssocNext; // fill in return data rKey = pAssocRet->key; rValue = pAssocRet->value; }