哈希算法是怎么實現的


有想過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;
        }
    }

 

 運行效果圖:

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM