hash存储,序列化和调整大小平衡

 

#include <cstdio>
#include <cstring>
#include "hashdict.h"


template<class KeyT,class CntT,class ValueT>
EA_COMMON::CHashDict<KeyT,CntT,ValueT>::CHashDict()
{}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::CHashDict<KeyT,CntT,ValueT>::~CHashDict()
{}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Create(CntT atHashNum,CntT atCnt)
{
 if(atHashNum == 0)
 {
  return enum_op_error;
 }
 
 m_oHashDict.m_tHashNum = atHashNum;
 m_oHashDict.m_tNodeNum = 0;
 m_oHashDict.m_tCnt = atCnt;
 
 m_oHashDict.m_oHashTbl.m_pHash = new STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>*[m_oHashDict.m_tHashNum];
 if(!m_oHashDict.m_oHashTbl.m_pHash)
 {
  return enum_op_error;
 }
 
 memset(m_oHashDict.m_oHashTbl.m_pHash,0,sizeof(STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>*)*m_oHashDict.m_tHashNum);
 
 m_oHashDict.m_pFirstBlock = new STRU_HASH_BLOCK<KeyT,CntT,ValueT>;
 if(!m_oHashDict.m_pFirstBlock)
 {
  delete [] m_oHashDict.m_oHashTbl.m_pHash;
  return enum_op_error;
 }
 
 memset(m_oHashDict.m_pFirstBlock->m_nHashNode,0,sizeof(STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>)*HASH_DICT_BLOCK_NUM);
 m_oHashDict.m_pFirstBlock->m_pNext = 0;
 
 m_oHashDict.m_pCurBlock = m_oHashDict.m_pFirstBlock;
 m_oHashDict.m_uiAvailNum = HASH_DICT_BLOCK_NUM;
 m_oHashDict.m_pCurNode = m_oHashDict.m_pCurBlock->m_nHashNode;
 
 return enum_op_ok;
}

template<class KeyT,class CntT,class ValueT>
bool EA_COMMON::CHashDict<KeyT,CntT,ValueT>::IsDelNode(STRU_DICT_NODE<KeyT,CntT,ValueT> *aoNode)
{
 if(aoNode->m_tKey == 0)
 {
  return true;
 }
 
 return false;
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Save(const char *apPath,const char *apFile)
{
 char lstrName[512];
 snprintf(lstrName,512,"%s/%s.info",apPath,apFile);
 
 //record info file
 FILE *lpFileInfo = fopen(lstrName,"w");
 fprintf(lpFileInfo,"hash_base=%u\nnode_num=%u\ncnt=%u\n",m_oHashDict.m_tHashNum,m_oHashDict.m_tNodeNum,m_oHashDict.m_tCnt);
 fclose(lpFileInfo);
 
 //record second level
 unsigned int *lpInfoCnt = new unsigned int[2*m_oHashDict.m_tHashNum];
 memset(lpInfoCnt,0,sizeof(unsigned int) * 2 * m_oHashDict.m_tHashNum);
 unsigned int *lpSkipCnt = lpInfoCnt;
 unsigned int *lpItemCnt = lpInfoCnt + m_oHashDict.m_tHashNum;

 unsigned int luiBlockCnt = 0,luiLoopCnt=0,luiNodeCnt=0;
 STRU_DICT_SAVE_NODE<KeyT,ValueT> *lpSave = new STRU_DICT_SAVE_NODE<KeyT,ValueT>[HASH_DICT_BLOCK_NUM];
 
 snprintf(lstrName,512,"%s/%s.data2",apPath,apFile);
 FILE *lpFileData2 = fopen(lstrName,"w");
 
 for(unsigned int i = 0;i < m_oHashDict.m_tHashNum;i++)
 {
  STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpHashNode = m_oHashDict.m_oHashTbl.m_pHash[i];
  
  lpSkipCnt[i] = luiNodeCnt;
  
  while(lpHashNode)
  {
   if(IsDelNode(lpHashNode))
   {
    lpHashNode = lpHashNode->m_pNext;
    continue;
   }
   
   lpSave[luiLoopCnt].m_tKey = lpHashNode->m_tKey;
   lpSave[luiLoopCnt].m_tValue = lpHashNode->m_tValue;
   
   lpItemCnt[i]++;
   luiLoopCnt++;
   luiNodeCnt++;
   
   if(luiLoopCnt >= HASH_DICT_BLOCK_NUM)
   {
    fwrite(lpSave,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),luiLoopCnt,lpFileData2);
    luiBlockCnt++;
    luiLoopCnt=0;
   }
   
   lpHashNode = lpHashNode->m_pNext;
  }
 }
 
 if(luiLoopCnt != 0)
 {
  fwrite(lpSave,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),luiLoopCnt,lpFileData2);
 }
 
 fclose(lpFileData2);
 delete [] lpSave;
 
 if((luiBlockCnt * HASH_DICT_BLOCK_NUM + luiLoopCnt != m_oHashDict.m_tNodeNum) || (luiNodeCnt != m_oHashDict.m_tNodeNum))
 {
  delete [] lpInfoCnt;
  return enum_op_error;
 }
 
 snprintf(lstrName,512,"%s/%s.data1",apPath,apFile);
 
 FILE *lpFileData1 = fopen(lstrName,"w");
 
 fwrite(lpSkipCnt,sizeof(unsigned int),m_oHashDict.m_tHashNum,lpFileData1);
 fwrite(lpItemCnt,sizeof(unsigned int),m_oHashDict.m_tHashNum,lpFileData1);
 
 fclose(lpFileData1);
 
 delete [] lpInfoCnt;
 
 m_oHashDict.m_tCnt++;
 
 return enum_op_ok; 
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Destroy()
{
 delete [] m_oHashDict.m_oHashTbl.m_pHash;
 
 STRU_HASH_BLOCK<KeyT,CntT,ValueT> *lpBlock = m_oHashDict.m_pFirstBlock;
 STRU_HASH_BLOCK<KeyT,CntT,ValueT> *lpTmp=0;;
 
 while(lpBlock)
 {
  lpTmp = lpBlock;
  lpBlock = lpBlock->m_pNext;
  delete [] lpTmp;
 }
 
 return enum_op_ok;
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Load(const char *apPath,const char *apFile,CntT atHashNum)
{
 char lstrName[512];
 snprintf(lstrName,512,"%s/%s.info",apPath,apFile);
 
 FILE *lpFileInfo = fopen(lstrName,"r");
 
 unsigned int luiHashNum = 0,luiNodeNum = 0,luiCnt = 0;
 if(fscanf(lpFileInfo,"hash_base=%u\nnode_num=%u\ncnt=%u\n",&luiHashNum,&luiNodeNum,&luiCnt) != 3)
 {
  fclose(lpFileInfo);
  return enum_op_error;
 }
 
 fclose(lpFileInfo);
 
 luiHashNum = atHashNum > 0 ? atHashNum:luiHashNum;
 
 if(CHashDict<KeyT,CntT,ValueT>::Create(luiHashNum,0) != enum_op_ok)
 {
  return enum_op_error;
 }
 
 snprintf(lstrName,512,"%s/%s.data2",apPath,apFile);
 FILE *lpFileData2 = fopen(lstrName,"r");
 
 STRU_DICT_SAVE_NODE<KeyT,ValueT> loNodeValue[HASH_DICT_BLOCK_NUM];
 unsigned int luiNodeCnt = 0,luiNodeRCnt=0;
 STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> loDictNode;
 while((luiNodeCnt=fread(loNodeValue,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),HASH_DICT_BLOCK_NUM,lpFileData2)) > 0)
 {
  for(int i = 0;i<luiNodeCnt;i++)
  {
   loDictNode.m_tKey = loNodeValue[i].m_tKey;
   loDictNode.m_tValue = loNodeValue[i].m_tValue;
   loDictNode.m_tCnt = -1;
   loDictNode.m_pNext = 0;
   
   Add(loDictNode,true);
  }
  
  luiNodeRCnt += luiNodeCnt;
 }
 
 fclose(lpFileData2);
 
 if(luiNodeRCnt != luiNodeNum)
 {
  return enum_op_error;
 }
 
 return enum_op_ok;
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Add(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode,bool abOverwrite)
{
 if(aoNode.m_tKey == 0)
 {
  return enum_add_invalid;
 }
 
 unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
 
 STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
 STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpInsNode=0,*lpAviNode=0;
 
 while(lpNode)
 {
  if(lpNode->m_tKey == aoNode.m_tKey)
  {
   lpInsNode = lpNode;
   break;
  }
  
  if(lpAviNode == 0 && lpNode->m_tKey == 0)
  {
   lpAviNode = lpNode;
  }
  
  lpNode = lpNode->m_pNext;  
 }
 
 ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
 
 if(lpInsNode)
 {
  if(abOverwrite)
  {
   lpInsNode->m_tValue = aoNode.m_tValue;
   m_oHashDict.m_tCnt++;
   loOpType = enum_add_replace;
  }
  else
  {
   loOpType = enum_add_exist;
  }
 }
 else
 {
  if(lpAviNode)
  {
   lpAviNode->m_tKey = aoNode.m_tKey;
   lpAviNode->m_tValue = aoNode.m_tValue;
   lpAviNode->m_tCnt = ++m_oHashDict.m_tCnt;
   m_oHashDict.m_tNodeNum++;
  }
  else
  {
   if(m_oHashDict.m_uiAvailNum == 0)
   {
    m_oHashDict.m_pCurBlock = new STRU_HASH_BLOCK<KeyT,CntT,ValueT>;
    
    memset(m_oHashDict.m_pCurBlock->m_nHashNode,0,sizeof(STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>) * HASH_DICT_BLOCK_NUM);
    
    m_oHashDict.m_pCurBlock->m_pNext = m_oHashDict.m_pFirstBlock;
    m_oHashDict.m_pFirstBlock = m_oHashDict.m_pCurBlock;
    m_oHashDict.m_uiAvailNum = HASH_DICT_BLOCK_NUM;
    m_oHashDict.m_pCurNode = m_oHashDict.m_pCurBlock->m_nHashNode;
   }
   
   lpInsNode = m_oHashDict.m_pCurNode;
   lpInsNode->m_pNext = 0;
   lpInsNode->m_tKey = aoNode.m_tKey;
   lpInsNode->m_tCnt = ++m_oHashDict.m_tCnt;
   lpInsNode->m_tValue = aoNode.m_tValue;
   
   if(m_oHashDict.m_oHashTbl.m_pHash[luiKey] == 0)
   {
    m_oHashDict.m_oHashTbl.m_pHash[luiKey] = lpInsNode;
   }
   else
   {
    lpInsNode->m_pNext = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
    m_oHashDict.m_oHashTbl.m_pHash[luiKey] = lpInsNode;
   }
   
   ++m_oHashDict.m_tNodeNum;
   --m_oHashDict.m_uiAvailNum;
   ++m_oHashDict.m_pCurNode;
  }
 }
 
 return loOpType; 
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Del(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode)
{
 ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
 
 unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
 
 STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
 
 while(lpNode)
 {
  if(lpNode->m_tKey == aoNode.m_tKey)
  {
   break;
  }
  
  lpNode = lpNode->m_pNext;
 }
 
 if(lpNode)
 {
  lpNode->m_tKey = 0;
  ++m_oHashDict.m_tCnt;
  --m_oHashDict.m_tNodeNum;
 }
 else
 {
  loOpType = enum_node_not_exist;
 }
 
 return loOpType;
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Modify(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode)
{
 ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
 
 unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
 
 STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
 
 while(lpNode)
 {
  if(lpNode->m_tKey == aoNode.m_tKey)
  {
   break;
  }
  
  lpNode = lpNode->m_pNext;
 }
 
 if(lpNode)
 {
  lpNode->m_tValue = aoNode.m_tValue;
  lpNode->m_tCnt = ++m_oHashDict.m_tCnt;
 }
 else
 {
  loOpType = enum_node_not_exist;
 }
 
 return loOpType;
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Find(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode)
{
 ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
 
 unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
 
 STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
 
 while(lpNode)
 {
  if(lpNode->m_tKey == aoNode.m_tKey)
  {
   break;
  }
  
  lpNode = lpNode->m_pNext;
 }
 
 if(lpNode)
 {
  aoNode.m_tValue = lpNode->m_tValue;
  aoNode.m_tCnt = lpNode->m_tCnt;
 }
 else
 {
  loOpType = enum_node_not_exist;
 }
 
 return loOpType;
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Adjust()
{
 unsigned int luiHashNum = m_oHashDict.m_tNodeNum % 2 ? m_oHashDict.m_tNodeNum/2 + 1:m_oHashDict.m_tNodeNum/2;
  
 STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> **lpHashTbl = new STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>*[luiHashNum];
 
 delete [] m_oHashDict.m_oHashTbl.m_pHash;
 
 m_oHashDict.m_oHashTbl.m_pHash = lpHashTbl;
 m_oHashDict.m_tHashNum = luiHashNum;
 
 STRU_HASH_BLOCK<KeyT,CntT,ValueT> *lpNodeBlock = m_oHashDict.m_pFirstBlock;
 
 unsigned int luiLoopCnt = HASH_DICT_BLOCK_NUM;
 unsigned int luiKey = 0;
 while(lpNodeBlock)
 {
  if(!lpNodeBlock->m_pNext)
  {
   luiLoopCnt = HASH_DICT_BLOCK_NUM - m_oHashDict.m_uiAvailNum;
   
   STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = lpNodeBlock->m_nHashNode;
   for(int i = 0;i<luiLoopCnt;i++)
   {
    if(lpNode[i].m_tKey)
    {
     luiKey = lpNode[i].m_tKey % luiHashNum;
    }
    else
    {
     luiKey = (luiKey + 1)%luiHashNum;
    }
    
    if(m_oHashDict.m_oHashTbl.m_pHash[luiKey])
    {
     lpNode[i].m_pNext = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
     m_oHashDict.m_oHashTbl.m_pHash[luiKey] = &lpNode[i];     
    }
    else
    {
     lpNode[i].m_pNext = 0;
     m_oHashDict.m_oHashTbl.m_pHash[luiKey] = &lpNode[i];
    }
   }
  }
  
  lpNodeBlock = lpNodeBlock->m_pNext;
 }
 
 return enum_op_ok; 
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::CSearchDict()
{}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::~CSearchDict()
{}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::Load(const char *apPath,const char *apFile)
{
 char lstrName[512];
 snprintf(lstrName,512,"%s/%s.info",apPath,apFile);
 
 FILE *lpFileInfo = fopen(lstrName,"r");
 
 unsigned int luiHashNum = 0,luiNodeNum = 0,luiCurCnt=0;
 
 if(fscanf(lpFileInfo,"hash_base=%u\nnode_num=%u\ncnt=%u\n",&luiHashNum,&luiNodeNum,&luiCurCnt) != 3)
 {
  fclose(lpFileInfo);
  return enum_op_error;
 }
 
 fclose(lpFileInfo);
 
 m_oSearchDict.m_tHashNum = luiHashNum;
 m_oSearchDict.m_tNodeNum = luiNodeNum;
 m_oSearchDict.m_ptHashSkip = new CntT[luiHashNum];
 m_oSearchDict.m_ptItemNum = new CntT[luiHashNum];
 
 FILE *lpFileData1 = 0,*lpFileData2 = 0;
 
 snprintf(lstrName,512,"%s/%s.data1",apPath,apFile);
 lpFileData1 = fopen(lstrName,"r");
 if(fread(m_oSearchDict.m_ptHashSkip,sizeof(CntT),luiHashNum,lpFileData1) != luiHashNum)
 {
  fclose(lpFileData1);
  delete [] m_oSearchDict.m_ptHashSkip;
  delete [] m_oSearchDict.m_ptItemNum;
  return enum_op_error;
 }
 
 if(fread(m_oSearchDict.m_ptItemNum,sizeof(CntT),luiHashNum,lpFileData1) != luiHashNum)
 {
  fclose(lpFileData1);
  delete [] m_oSearchDict.m_ptHashSkip;
  delete [] m_oSearchDict.m_ptItemNum;
  return enum_op_error;
 }
 
 fclose(lpFileData1);
 
 snprintf(lstrName,512,"%s/%s.data2",apPath,apFile);
 lpFileData2 = fopen(lstrName,"r");
 
 m_oSearchDict.m_pNodes = new STRU_DICT_SAVE_NODE<KeyT,ValueT>[luiNodeNum];
 if(fread(m_oSearchDict.m_pNodes,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),luiNodeNum,lpFileData2) != luiNodeNum)
 {
  delete [] m_oSearchDict.m_ptHashSkip;
  delete [] m_oSearchDict.m_ptItemNum;
  delete [] m_oSearchDict.m_pNodes;
  return enum_op_error;
 }
 
 fclose(lpFileData2);
 
 return enum_op_ok;
}

template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::Destroy()
{
 delete [] m_oSearchDict.m_ptHashSkip;
 delete [] m_oSearchDict.m_ptItemNum;
 delete [] m_oSearchDict.m_pNodes;
 
 return enum_op_error;
}
 
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::Find(STRU_DICT_SAVE_NODE<KeyT,ValueT> &aoNode)
{
 unsigned int luiKey = aoNode.m_tKey % m_oSearchDict.m_tHashNum;
 
 STRU_DICT_SAVE_NODE<KeyT,ValueT> *lpNode = 0;
 
 for(unsigned int i = 0;i < m_oSearchDict.m_ptItemNum[luiKey];i++)
 {
  int liIndex = m_oSearchDict.m_ptHashSkip[luiKey] + i;
  lpNode = &m_oSearchDict.m_pNodes[liIndex];
  
  if(lpNode->m_tKey == aoNode.m_tKey)
  {
   aoNode.m_tValue = lpNode->m_tValue;
   return enum_op_ok;
  }
 }
 
 return enum_op_error;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值