鱼C论坛

 找回密码
 立即注册
查看: 2724|回复: 1

[技术交流] 一个SymbolTable类(哈希表的应用)

[复制链接]
发表于 2014-3-16 22:19:32 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
直接上代码吧。
main.cpp
  1. #include "List.h"
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cassert>

  5. class StringBuffer
  6. {
  7. public:
  8.         explicit StringBuffer (int size)
  9.                 : _curOffset (0), _bufSize (size)
  10.         {
  11.                 _buf = new char [size];
  12.         }
  13.         ~StringBuffer ()
  14.         {
  15.                 delete []_buf;
  16.         }
  17.         bool WillFit (int len) const
  18.         {
  19.                 return _curOffset + len + 1 < _bufSize;
  20.         }
  21.         void Add (char const * str)
  22.         {
  23.                 strcpy (&_buf [_curOffset], str);
  24.                 _curOffset += strlen (str) + 1;
  25.         }
  26.         int GetOffset () const
  27.         {
  28.                 return _curOffset;
  29.         }
  30.         bool IsEqual (int offStr, char const * str) const
  31.         {
  32.                 char const * strStored = &_buf [offStr];
  33.                 return strcmp (str, strStored) == 0;
  34.         }
  35.         char const * GetString (int offStr) const
  36.         {
  37.                 return &_buf [offStr];
  38.         }
  39. private:
  40.         int                _bufSize;
  41.         char  * _buf;
  42.         int     _curOffset;
  43. };

  44. class HTable
  45. {
  46. public:
  47.         explicit HTable (int size): _size (size)
  48.         {
  49.                 _aList = new List [size];
  50.         }
  51.         ~HTable ()
  52.         {
  53.                 delete []_aList;
  54.         }
  55.         // return a short list of candidates
  56.         List & find (char const * str) const;
  57.         // add another string->id mapping
  58.         void insert (char const * str, int id);
  59. private:
  60.         // the hashing function
  61.         int hash (char const * str) const;

  62.         List  * _aList; // an array of (short) lists
  63.         int         _size;
  64. };

  65. // Find the list in the hash table that may contain
  66. // the id of the string we are looking for

  67. List & HTable::find (char const * str) const
  68. {
  69.         int i = hash (str);
  70.         return _aList [i];
  71. }

  72. void HTable::insert (char const * str, int id)
  73. {
  74.         int i = hash (str);
  75.         _aList [i].insert (id);
  76. }

  77. int HTable::hash (char const * str) const
  78. {
  79.         // no empty strings, please
  80.         assert (str != 0 && str [0] != 0);
  81.         unsigned h = str [0];
  82.         for (int i = 1; str [i] != 0; ++i)
  83.         {
  84.                 h = (h << 4) + str [i];
  85.                 unsigned long g = h & 0xf0000000L;
  86.                 if (g) h ^= g >> 24;
  87.                 h &= -g;
  88.         }
  89.         return h % _size; // remainder
  90. }

  91. const int idNotFound = -1;

  92. // String table maps strings to ints
  93. // and ints to strings

  94. class SymbolTable
  95. {
  96. public:
  97.         explicit SymbolTable (int size);
  98.         ~SymbolTable ();
  99.         int ForceAdd (char const * str, int len);
  100.         int Find (char const * str) const;
  101.         char const * GetString (int id) const;
  102. private:
  103.         HTable                        _htab;         // string -> ids
  104.         int                                _maxId;
  105.         int                          * _offStr; // id -> offset
  106.         int                                _curId;
  107.         StringBuffer        _strBuf; // offset -> string
  108. };

  109. SymbolTable::SymbolTable (int size)
  110.         : _curId (0),
  111.           _maxId (size),
  112.           _htab (size + 1),
  113.           _strBuf (size * 10)
  114. {
  115.         _offStr = new int [size];
  116. }

  117. SymbolTable::~SymbolTable ()
  118. {
  119.         delete []_offStr;
  120. }

  121. int SymbolTable::ForceAdd (char const * str, int len)
  122. {
  123.         // is there enough space?
  124.         if (_curId == _maxId || !_strBuf.WillFit (len))
  125.         {
  126.                 return idNotFound;
  127.         }
  128.         // point to the place where the string will be stored
  129.         _offStr [_curId] = _strBuf.GetOffset ();
  130.         _strBuf.Add (str);
  131.         // add mapping to hash table
  132.         _htab.insert (str, _curId);
  133.         ++_curId;
  134.         return _curId - 1;
  135. }

  136. int SymbolTable::Find (char const * str) const
  137. {
  138.         // Get a short list from hash table
  139.         List & list = _htab.find (str);
  140.         // Iterate over this list
  141.         for (List::iterator it = list.begin();
  142.                  it != list.end();
  143.                  ++it)
  144.         {
  145.                 int id = *it;
  146.                 int offStr = _offStr [id];
  147.                 if (_strBuf.IsEqual (offStr, str))
  148.                 return id;
  149.         }
  150.         return idNotFound;
  151. }

  152. // map integer into string. Must be valid id

  153. char const * SymbolTable::GetString (int id) const
  154. {
  155.         assert (id >= 0);
  156.         assert (id < _curId);
  157.         int offStr = _offStr [id];
  158.         return _strBuf.GetString (offStr);
  159. }

  160. int main()
  161. {
  162.         SymbolTable strTable(100);
  163.         strTable.ForceAdd ("One", 3);
  164.         strTable.ForceAdd ("Two", 3);
  165.         strTable.ForceAdd ("Three", 5);

  166.         int id = strTable.Find ("One");
  167.         std::cout << "One at " << id << std::endl;
  168.         id = strTable.Find ("Two");
  169.         std::cout << "Two at " << id << std::endl;
  170.         id = strTable.Find ("Three");
  171.         std::cout << "Three at " << id << std::endl;
  172.         id = strTable.Find ("Minus one");
  173.         std::cout << "Minus one at " << id << std::endl;

  174.         std::cout << "String 0 is "
  175.                         << strTable.GetString (0) << std::endl;
  176.         std::cout << "String 1 is "
  177.                         << strTable.GetString (1) << std::endl;
  178.         std::cout << "String 2 is "
  179.                         << strTable.GetString (2) << std::endl;
  180.         return 0;
  181. }
复制代码
List.h可以参考http://bbs.fishc.com/thread-44344-1-1.html
整体来说,大家可以看出,这个SymbolTable很好的处理了Hash值的collision,那就是使用多个短链表存储同一位置的字符~
三个类放在一起,也许会看起来比较乱。但是,其实它们是相关的。数据真正存储的地方其实是StringBuffer的_buf字符指针里面。就这样吧。今天我们英语配音比赛得了第一名,好开心啊。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2014-3-17 00:25:54 | 显示全部楼层
谢谢分享资源  祝你马上有财
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-18 03:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表