重复发明轮子 自己实现哈希表。

Posted bywayboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重复发明轮子 自己实现哈希表。相关的知识,希望对你有一定的参考价值。

      首先想用汇编写的。但写到最后晕头转向。没办法。先用C++验证一遍自己的思路吧。代码如下。

 

  1. CHashMap::CHashMap()
  2. {
  3.     m_size  = 100;
  4.     m_count = 0;
  5.     m_nodes = (PCNODE)malloc(sizeof(CNODE)*100);
  6.     ZeroMemory(m_nodes,sizeof(CNODE)*100);
  7. }
  8. CHashMap::~CHashMap()
  9. {
  10.     for(int i=0;i<m_size;i++)
  11.     {
  12.         PCNODE cur_node = m_nodes+i;
  13.         if(cur_node->left)
  14.             _Del_X(cur_node->left);
  15.         if(cur_node->right)
  16.             _Del_X(cur_node->right);
  17.     }
  18.     free(m_nodes);
  19. }
  20. BOOL CHashMap::Set(DWORD key,DWORD value)
  21. {
  22.     if(m_count/m_size>=0.72)
  23.     {
  24.         // 重建哈希表 尺寸是原来的哈希表的双倍。
  25.         DWORD new_size  = m_size*2;
  26.         PCNODE  new_nodes   =  (PCNODE)malloc(sizeof(CNODE)*new_size);
  27.         ZeroMemory(new_nodes,sizeof(CNODE)*new_size);
  28.         for(int i=0;i<m_size;i++)
  29.         {
  30.             PCNODE cur_node = m_nodes+i;
  31.             if(cur_node->key)
  32.             {
  33.                 //添加当前节点。
  34.                 PCNODE add_node = _GetAddress_X(new_nodes,new_size,cur_node->key);
  35.                 if(add_node) add_node->value=cur_node->value;
  36.                 //遍历子节点,并且要删除旧的。
  37.                 if(cur_node->right)
  38.                     _SetAndDel_X(new_nodes,new_size,cur_node->right);
  39.                 if(cur_node->left)
  40.                     _SetAndDel_X(new_nodes,new_size,cur_node->left);
  41.             }
  42.         }
  43.         //删除旧的.
  44.         free(m_nodes);
  45.         m_nodes = new_nodes;
  46.         m_size = new_size;
  47.     }
  48.     PCNODE node;
  49.     if(node= _GetAddress_X(m_nodes,m_size,key))
  50.     {
  51.         node->value=value;
  52.         m_count++;
  53.         return TRUE;
  54.     }
  55.     return FALSE;
  56. }
  57. DWORD CHashMap::Get(DWORD key)
  58. {
  59.     // 先定位到数据。比较键值,寻找节点。最后返回需要的值。
  60.     DWORD pos= key % m_size;
  61.     PCNODE node=m_nodes+pos;
  62.     while(node){
  63.         if(key>node->key)
  64.             node = node->right;
  65.         else if(key<node->key)
  66.             node = node->left;
  67.         else
  68.             return node->value;
  69.     }
  70.     return NULL;
  71. }
  72. BOOL CHashMap::Exists(DWORD key)
  73. {
  74.     DWORD pos= key % m_size;
  75.     PCNODE node=m_nodes+pos;
  76.     while(node){
  77.         if(key>node->key)
  78.             node = node->right;
  79.         else if(key<node->key)
  80.             return TRUE;
  81.         else
  82.             return node->value;
  83.     }
  84.     return FALSE;
  85. }
  86. BOOL CHashMap::Del(DWORD key)
  87. {
  88.     DWORD pos= key % m_size;
  89.     PCNODE par_node = NULL,cur_node,node=m_nodes+pos;
  90.     if(NULL == node->key) return FALSE;
  91.     while(node){
  92.         
  93.         if(key>node->key){
  94.             par_node = node;
  95.             node = node->right;
  96.         }else if(key<node->key){
  97.             par_node = node;
  98.             node = node->left;
  99.         }else{
  100.             cur_node = node;
  101.             break;
  102.         }
  103.     }
  104.     if(!node) return FALSE; //没有找到 返回了
  105.     if(!par_node) //根节点的情况
  106.     {
  107.         if (cur_node->right)
  108.         {
  109.             PCNODE left_node = cur_node->left;
  110.             *cur_node = *cur_node->right;
  111.             if(left_node){
  112.                 //挂到最左边去。
  113.                 while(cur_node->left){
  114.                     cur_node = cur_node->left;
  115.                 }
  116.                 cur_node->left = left_node;
  117.             }
  118.         }else if(cur_node->left)
  119.         {
  120.             //没有右边节点的情况.
  121.             *cur_node = *cur_node->left;
  122.         }else{
  123.             //啥也没有的情况
  124.             cur_node->value = cur_node->key = 0;
  125.             cur_node->left=cur_node->right=NULL;
  126.         }
  127.         return TRUE;
  128.     }
  129.     /* 不是根节点的情况 需要 释放 cur_node*/
  130.     if(cur_node->right){
  131.         par_node->right=cur_node->right;
  132.         //左边的节点挂到右边的最左边。
  133.         if(cur_node->left){
  134.             node = cur_node;
  135.             while(node->left){node=node->left;}
  136.             node->left=cur_node->left;
  137.         }
  138.     }else if(cur_node->left){
  139.         //不存在右边的情况。
  140.         par_node->left=cur_node->left;
  141.     }else
  142.     {
  143.         if(par_node->left == cur_node)
  144.             par_node->left=NULL;
  145.         else
  146.             par_node->right=NULL;
  147.     }
  148.     free(cur_node);
  149.     return TRUE;
  150. }
  151. // 这是一个静态方法,复制新的节点,并删除旧的节点。
  152. void CHashMap::_SetAndDel_X(PCNODE arg_nodes,DWORD arg_size,PCNODE arg_node)
  153. {
  154.     PCNODE add_node = _GetAddress_X(arg_nodes,arg_size,arg_node->key);
  155.     if(add_node) add_node->value=arg_node->value;
  156.     if(arg_node->right)
  157.         _SetAndDel_X(arg_nodes,arg_size,arg_node->right);
  158.     if(arg_node->left)
  159.         _SetAndDel_X(arg_nodes,arg_size,arg_node->left);
  160.     free(arg_node);
  161. }
  162. void CHashMap::_Del_X(PCNODE arg_node)
  163. {
  164.     if(arg_node->right)
  165.         _Del_X(arg_node);
  166.     if(arg_node->left)
  167.         _Del_X(arg_node);
  168.     free(arg_node);
  169. }
  170. /*
  171.     如果相同键值的数据存在,会返回空。
  172.     这个方法是静态的。
  173.     如果存在,它会给我一个空间。如果不存在。它会分配好一个新的地址。
  174. */
  175. PCNODE CHashMap::_GetAddress_X(PCNODE arg_node,DWORD arg_size,DWORD key)
  176. {
  177.     DWORD pos= key % arg_size;
  178.     PCNODE t_node,node=arg_node+pos;
  179.     if(node->key==0){
  180.         node->key = key;
  181.         return node;
  182.     }
  183.     while (node)
  184.     {
  185.         t_node = node;
  186.         if(key>node->key)
  187.             node=node->right;
  188.         else if(key == node->key)
  189.             return NULL;
  190.         else
  191.             node=node->left;
  192.     }
  193.     node = (PCNODE)malloc(sizeof(CNODE));
  194.     node->key=key;node->left=node->right = NULL;
  195.     if(key>t_node->key)
  196.         t_node->right = node;
  197.     else
  198.         t_node->left = node;
  199.     return node;
  200. }

头文件:

 

  1. class CHashMap  
  2. {
  3. public:
  4.     CHashMap();
  5.     BOOL Set(DWORD key,DWORD value);//设置数据
  6.     DWORD Size(){return m_size;}    //取容量尺寸
  7.     DWORD Count(){return m_count;}  //取数据数目
  8.     DWORD Get(DWORD key);           //取数据
  9.     BOOL  Del(DWORD key);           //删除数据
  10.     BOOL Exists(DWORD key);         //数据是否存在
  11.     virtual ~CHashMap();
  12. private:
  13.     static PCNODE _GetAddress_X(PCNODE arg_node,DWORD arg_size,DWORD key);
  14.     static void _SetAndDel_X(PCNODE arg_nodes,DWORD arg_size,PCNODE arg_node);
  15.     void _Del_X(PCNODE arg_node);
  16. protected:
  17.     DWORD m_size;
  18.     DWORD m_count;
  19.     PCNODE m_nodes;
  20. };

以上是关于重复发明轮子 自己实现哈希表。的主要内容,如果未能解决你的问题,请参考以下文章

自己动手实现java数据结构哈希表

leetcode 数据结构 探索哈希表

哈希表原理及简单设计

[Codevs 1230]元素查找(手写哈希表)

STL 是不是包含哈希表? [复制]

redis源码学习看看redis的“哈希表”实现