有想過hash["A1"] = DateTime.Now;這句是怎么實現的嗎?我們來重溫下學校時代就學過的哈希算法吧。
我們要寫個class,實現如下主程序調用:
一看,也確實挺簡單的,就是一個所引器,如下:
程序中要保存的對象,最終是要保存在一個數組中的,而且需要通過一個轉換函數來進行string key與數組Index的Map,如下:
private int MapString2Int(string key)
{
int hashIndex=0;
char[] keyAry = key.ToCharArray();
foreach (var c in keyAry)
hashIndex += (int)c;
hashIndex = hashIndex % lstArray.Capacity;
return hashIndex;
}
這個函數是遍歷string key的每個char,累加,最終取模(同數組的長度),這樣得出的一個value肯定就在數組范圍內。
如果2個key轉換出來的index相同呢?會導致沖突,一個最簡單的解決辦法是把數組中的每個元素變成List, 也就是說,如果string key轉換后出現了相同的Index,沒關系,只要把那2個元素都放在那個Index所標識的數組位置中即可,本文中用的是List<Tuple<string, object>>。
下面是整個程序的代碼:
class MyHash
{
private const int defaultSize = 99999;
private List<List<Tuple<string, object>>> lstArray = new List<List<Tuple<string, object>>>(defaultSize);
public MyHash()
{
int i = lstArray.Capacity;
while(i>=0)
{
lstArray.Add(new List<Tuple<string,object>>());
i--;
}
}
public object this[string key]
{
get
{
EnsureNotNull(key);
List<Tuple<string, object>> lst;
Tuple<string, object> obj = FindByKey(key, out lst);
if (obj == null)
throw new Exception("Key不存在");
return obj.Item2;
}
set
{
EnsureNotNull(key);
List<Tuple<string, object>> lst;
Tuple<string, object> obj = FindByKey(key, out lst);
if (obj!=null)
lst.Remove(obj);
lst.Add(new Tuple<string, object>(key, value));
}
}
private Tuple<string, object> FindByKey(string key, out List<Tuple<string, object>> lst)
{
int hashIndex = MapString2Int(key);
lst = lstArray[hashIndex];
Tuple<string, object> obj = null;
for (var i = 0; i < lst.Count; i++)
{
if (lst[i].Item1 == key)
{
obj = lst[i];
break;
}
}
return obj;
}
private static void EnsureNotNull(string key)
{
if (key == null || key.Trim().Length == 0)
throw new Exception("Key不能為空");
}
private int MapString2Int(string key)
{
int hashIndex=0;
char[] keyAry = key.ToCharArray();
foreach (var c in keyAry)
hashIndex += (int)c;
hashIndex = hashIndex % lstArray.Capacity;
Console.WriteLine(string.Format("{0}相應的Index為:{1}", key, hashIndex));
return hashIndex;
}
}
運行效果圖:
新聞熱點
疑難解答