c#哈希算法的实现方法及思路
作者:
有想过hash["A1"] = DateTime.Now;这句是怎么实现的吗?我们来重温下学校时代就学过的哈希算法吧。
我们要写个class,实现如下主程序调用:
static void Main(string[] args)
{
MyHash hash = new MyHash();
hash["A1"] = DateTime.Now;
hash["A2"] = 1;
Console.WriteLine(Convert.ToString(hash["A1"]));
Console.WriteLine(Convert.ToString(hash["A2"]));
}
一看,也确实挺简单的,就是一个所引器,如下:
class MyHash
{
public object this[string key]
{
get
{
}
set
{
}
}
}
程序中要保存的对象,最终是要保存在一个数组中的,而且需要通过一个转换函数来进行string key与数组Index的Map,如下:
private List<List<Tuple<string, object>>> lstArray = new List<List<Tuple<string, object>>>(defaultSize);
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 Program
{
static void Main(string[] args)
{
MyHash hash = new MyHash();
hash["A1"] = DateTime.Now;
hash["A2"] = 1;
Console.WriteLine(Convert.ToString(hash["A1"]));
Console.WriteLine(Convert.ToString(hash["A2"]));
}
}
    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;
        }
    }
运行效果图:

