|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
直接上代码吧。
main.cpp
- #include "List.h"
- #include <iostream>
- #include <cstring>
- #include <cassert>
- class StringBuffer
- {
- public:
- explicit StringBuffer (int size)
- : _curOffset (0), _bufSize (size)
- {
- _buf = new char [size];
- }
- ~StringBuffer ()
- {
- delete []_buf;
- }
- bool WillFit (int len) const
- {
- return _curOffset + len + 1 < _bufSize;
- }
- void Add (char const * str)
- {
- strcpy (&_buf [_curOffset], str);
- _curOffset += strlen (str) + 1;
- }
- int GetOffset () const
- {
- return _curOffset;
- }
- bool IsEqual (int offStr, char const * str) const
- {
- char const * strStored = &_buf [offStr];
- return strcmp (str, strStored) == 0;
- }
- char const * GetString (int offStr) const
- {
- return &_buf [offStr];
- }
- private:
- int _bufSize;
- char * _buf;
- int _curOffset;
- };
- class HTable
- {
- public:
- explicit HTable (int size): _size (size)
- {
- _aList = new List [size];
- }
- ~HTable ()
- {
- delete []_aList;
- }
- // return a short list of candidates
- List & find (char const * str) const;
- // add another string->id mapping
- void insert (char const * str, int id);
- private:
- // the hashing function
- int hash (char const * str) const;
- List * _aList; // an array of (short) lists
- int _size;
- };
- // Find the list in the hash table that may contain
- // the id of the string we are looking for
- List & HTable::find (char const * str) const
- {
- int i = hash (str);
- return _aList [i];
- }
- void HTable::insert (char const * str, int id)
- {
- int i = hash (str);
- _aList [i].insert (id);
- }
- int HTable::hash (char const * str) const
- {
- // no empty strings, please
- assert (str != 0 && str [0] != 0);
- unsigned h = str [0];
- for (int i = 1; str [i] != 0; ++i)
- {
- h = (h << 4) + str [i];
- unsigned long g = h & 0xf0000000L;
- if (g) h ^= g >> 24;
- h &= -g;
- }
- return h % _size; // remainder
- }
- const int idNotFound = -1;
- // String table maps strings to ints
- // and ints to strings
- class SymbolTable
- {
- public:
- explicit SymbolTable (int size);
- ~SymbolTable ();
- int ForceAdd (char const * str, int len);
- int Find (char const * str) const;
- char const * GetString (int id) const;
- private:
- HTable _htab; // string -> ids
- int _maxId;
- int * _offStr; // id -> offset
- int _curId;
- StringBuffer _strBuf; // offset -> string
- };
- SymbolTable::SymbolTable (int size)
- : _curId (0),
- _maxId (size),
- _htab (size + 1),
- _strBuf (size * 10)
- {
- _offStr = new int [size];
- }
- SymbolTable::~SymbolTable ()
- {
- delete []_offStr;
- }
- int SymbolTable::ForceAdd (char const * str, int len)
- {
- // is there enough space?
- if (_curId == _maxId || !_strBuf.WillFit (len))
- {
- return idNotFound;
- }
- // point to the place where the string will be stored
- _offStr [_curId] = _strBuf.GetOffset ();
- _strBuf.Add (str);
- // add mapping to hash table
- _htab.insert (str, _curId);
- ++_curId;
- return _curId - 1;
- }
- int SymbolTable::Find (char const * str) const
- {
- // Get a short list from hash table
- List & list = _htab.find (str);
- // Iterate over this list
- for (List::iterator it = list.begin();
- it != list.end();
- ++it)
- {
- int id = *it;
- int offStr = _offStr [id];
- if (_strBuf.IsEqual (offStr, str))
- return id;
- }
- return idNotFound;
- }
- // map integer into string. Must be valid id
- char const * SymbolTable::GetString (int id) const
- {
- assert (id >= 0);
- assert (id < _curId);
- int offStr = _offStr [id];
- return _strBuf.GetString (offStr);
- }
- int main()
- {
- SymbolTable strTable(100);
- strTable.ForceAdd ("One", 3);
- strTable.ForceAdd ("Two", 3);
- strTable.ForceAdd ("Three", 5);
- int id = strTable.Find ("One");
- std::cout << "One at " << id << std::endl;
- id = strTable.Find ("Two");
- std::cout << "Two at " << id << std::endl;
- id = strTable.Find ("Three");
- std::cout << "Three at " << id << std::endl;
- id = strTable.Find ("Minus one");
- std::cout << "Minus one at " << id << std::endl;
- std::cout << "String 0 is "
- << strTable.GetString (0) << std::endl;
- std::cout << "String 1 is "
- << strTable.GetString (1) << std::endl;
- std::cout << "String 2 is "
- << strTable.GetString (2) << std::endl;
- return 0;
- }
复制代码 List.h可以参考http://bbs.fishc.com/thread-44344-1-1.html
整体来说,大家可以看出,这个SymbolTable很好的处理了Hash值的collision,那就是使用多个短链表存储同一位置的字符~
三个类放在一起,也许会看起来比较乱。但是,其实它们是相关的。数据真正存储的地方其实是StringBuffer的_buf字符指针里面。就这样吧。今天我们英语配音比赛得了第一名,好开心啊。
|
|