主要目的是實現基於字典的字串壓縮時,快速的判斷乙個詞是否出現在字典中並獲取其編碼。
這種方法速度挺快,而且方便檔案讀寫,節約記憶體空間,主要是有趣。
#pragma once
/** 1.如果使用合理的雜湊演算法,若雜湊值可以有無限位,那麼某些雜湊演算法得到的雜湊值不可能相同,
* 自然溢位得到的32位雜湊值相同的概率也是很小的,除留餘數法取位址後衝突率大大增加,所以除數的選取至關重要。
* * 2.此處使用額外的兩個雜湊值校驗,不進行字串鍵的比較,所以當雜湊表只是用來查詢值或者
* 判斷鍵的存在性時,不需要儲存字串本身,但是為了擴容時的重定位,需要儲存用於定址的那個雜湊值。
* * 3.需要至少兩個雜湊值來校驗用以保證正確性,既然需要儲存用於定址的那個雜湊值(未除留餘數前的),
* 又知道衝突主要來自於除留餘數之後,那麼這個雜湊值仍然具有校驗價值,所以只需要額外計算乙個
* 校驗雜湊值即可,但是需要使用完全無關聯的雜湊演算法計算兩個雜湊值,可能安全性不如計算三個雜湊值好,
* 但是測試了許多的資料沒有出現錯誤的情況。
* * 4.採用線性探測法來處理衝突,那麼當表長較小時,由於衝突的疊加勢必會有較多的衝突,所以表的裝填因子不宜
* 過大(要小於等於0.5比較好),也就是會有較多的空間浪費,所以適合於資料量不是太大的情況。
* * 5.對於開放定址處理衝突的方法,不能輕易刪除某個鍵,因為可能會阻斷其他鍵的查詢路徑(可以定期維護,
* 但是麻煩),所以不適合有刪除鍵操作的情況。
* * 6.根據線性探測法衝突疊加的性質可知,後來插入的鍵衝突概率會增大,如果已知大部分待查詢的鍵都可以查詢成功,
* 那麼就可以按查詢頻率插入鍵來減少平均查詢長度,但是對於查詢失敗的鍵不管用。
* * 7.使用類似hashmap的表長(2^n)及動態擴容方法及(key & (tablelength - 1))的取址方法會比較簡潔,但是實驗的資料
* 雜湊的不如素數表長好。
*/#ifdef _debug
#include
#endif
typedef
unsigned
int uint;
static
const uint alterlength=
;#define max_table_length 359339171u
/* 若鍵個數大於最大表長則仍會使用最大表長,此時插入會死迴圈,但是一般是不太大的資料量使用,故沒有再檢查。 */
template
class stringhashtable
}hash_node,
* hash_table;
/* 規範化表長 */
uint normtablelength
(uint tablelength)
;/* 暴雪的那個雜湊函式不明白,用了簡單的字串雜湊函式 */
void
hash
(char
* str, uint strlength, uint& key, uint& check)
;/* 擴容時的插入函式 */
void
insert
(hash_node& hashnode)
;/* 嘗試擴容 */
void
tryexpandtable()
;private:
hash_table table;
// 雜湊表
uint tablelength;
// 雜湊表長
uint usedindexcounts;
// 占用位置計數
uint lengthindex;
// 表長在候選表中的索引
valuetype badvalue;
// 初始時使用此值填充表,並用以判斷位置是否空閒};
template
inline stringhashtable::
stringhashtable
(valuetype badvalue)
template
inline stringhashtable::
stringhashtable
(valuetype badvalue, uint inittablelength)
template
inline stringhashtable::
~stringhashtable()
}template
inline uint stringhashtable::
_tablelength()
template
inline uint stringhashtable::
_usedindexcounts()
template
inline
void stringhashtable::
insert
(char
* str, uint strlength, valuetype value)
#ifdef _debug
std:
:cout << conflict << std:
:endl;
#endif
table[addr]
.key = key;
table[addr]
.check = check;
table[addr]
.value = value;
usedindexcounts++
;tryexpandtable()
;}template
inline valuetype stringhashtable::
getvalue
(char
* str, uint strlength)
return table[addr]
.value;
}template
inline uint stringhashtable::
normtablelength
(uint tablelength)
}template
inline
void stringhashtable::
hash
(char
* str, uint strlength, uint& key, uint& check)
//key ^= (key >> 16); // 高低位擾動
}template
inline
void stringhashtable::
insert
(hash_node& hashnode)
table[addr]
= hashnode;
}#define max_loadfactor 0.5f
template
inline
void stringhashtable::
tryexpandtable()
delete[
] temptable;
}
16 字串雜湊 雜湊表
這個方法叫做字串字首雜湊法 先求出來每個字首的雜湊值 問題1 如何來定義某乙個字首的雜湊值 把這個字串看成是乙個p進製的數 每一位上的字母的ascii碼,就是這一位上的數 最後mod上乙個很小的數,就對映到0 q 1 這樣就可以把乙個字串轉換為乙個數字 注意事項1 一般情況下,不能把某個字母對映成0...
字串雜湊
參照演算法筆記p109,甲級1039 先假設字串均由大寫字母a z構成。在這個基礎上,不妨把a z視為0 25,這樣就把26個大寫字母對應到了26進製中。接著,按照將26進製轉化為10進製的思路,由進製的轉換結論可知,在進製轉換過程中,得到的10進製肯定是唯一的,由此便可實現將字串對映為整數的需求 ...
字串雜湊
昨天做了一道字串雜湊的題,感覺還好理解。今天的題看了 不知道為什麼,搜來搜去發現不知道的東西還很多,網上找到的東西也都是很零散,書上也沒有系統的講解。先自己整理一下這些零散的知識 關於字串涉及到的演算法大概有 hash kmp trie ac自動機等等,現在還都不明白是怎麼回事,這次先研究字串has...