C#編程(五十四)----------Lookup類和有序字典


原文鏈接: http://blog.csdn.net/shanyongxu/article/details/47071607

 

Lookup

Dictionary<Tkey,TValue>只為每個鍵支持一個值.新類Lookup<Tkey,TValue>.NET3.5中新增的,它類似與Dictionary<Tkey,TElement>,但把鍵映射帶一個值集上.這個類在程序及System.Core中實現,System,Linq命名空間定義.

 

Lookup<Tkey,TElement>的方法和屬性如下表:

屬性名或者方法名

說明

Count

屬性Count返回集合中的元素個數

Item

使用索引器可以根據鍵訪問特定的元素.因為同一個鍵可以對應多個值,所以這個屬性返回所有值的枚舉

Contain()

方法Contains()根據使用用Key參數傳送元素,返回一個布爾值

ApplyResultSelector()

ApplyResultSelector(0根據傳送給它的轉換函數,轉換每一項,返回一個集合

Loopup<TKey,TElement>不能像一般的字典那樣創建,而必須調用方法ToLookup(),它返回一個Lookup<TKey,TElement>對象.方法ToLookup()是一個擴展方法,可以用於實現了IEnumerable<T>的所有類.

 

 

當一個Key要求對應多個value情況ToLookup方法非常有用,ToLookup返回一種特殊的數據結構,類似SQL中的group,可以把集合分組並且可以用索引訪問這些元素,案例:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace Lookup

{

 

    class Program

    {

        static void Main(string[] args)

        {

            //創建一個string類型的數組

            string[] array = { "cat","dog","horse"};

            //生成查找結構

            var lookup = array.ToLookup(item => item.Length);

            //枚舉字符長度3的串

            foreach (var item in lookup[3])

            {

                Console.WriteLine("3 = "+item);

            }

 

            //枚舉字符長度5的串

            foreach (var item in lookup[5])

            {

                Console.WriteLine("5 = " + item);

            }

            //枚舉分組

 

            foreach (var grouping in lookup)

            {

                Console.WriteLine("Grouping : ");

                foreach (var item in grouping)

                {

                    Console.WriteLine(item);

                }

            }

            Console.ReadKey();

        }        

    }

}

 

 

上面的案例是通過數組元素的字符串長度為Key分組,也就是字符長度相同的元素的Key是一樣的,索引下標也是一樣.比如以通過lookup[3]訪問,horse要用lookup[5]來訪問.

 

 

有序字典

SortedDictionary<TKey,TValue>類是一個二叉搜索樹,其中的元素根據鍵來排序.該鍵類型必須實現IComparable<TKey>接口.如果鍵的類型不能排序,則還可以創建一個實現了IComparer<TKey>接口的比較器,將比較器用作有序字典的構造函數的一個參數.

SortedDictionary<TKey,TValue>類和SortedList<TKey,TValue>類的功能類似.但因為SortedList<TKey,TValue>實現為一個基於數組的列表,SortedDictionary<TKey,TValye>類實現為一個字典,所以他們有不同的特征:

1.SortedList<Tkey,TValue>類使用的內存比SortedDictionary<TKey,TValue>類少

2.SortedDictionary<TKey,TValue>類的元素插入和刪除速度比較快

3.在用已排好序的數據填充集合時,若不需要修改容量,SortedList<TKey,TValue>類就比較快.

 

案例:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace 有序字典

{

    class Program

    {

        static void Main(string[] args)

        {

            //SortedList<TKey,TValue>使用的內存少

            //SortedDictionary<TKey,TValue>元素插入和刪除速度快

            //鍵要實現IComparable<in T>接口

            SortedDictionary<EmployeeID, Person> sd = new SortedDictionary<EmployeeID, Person>();

            sd.Add(new EmployeeID(3),new Person("中國", "張飛", 40));

            sd.Add(new EmployeeID(20), new Person("中國", "關羽", 43));

            sd.Add(new EmployeeID(4), new Person("中國", "劉備", 45));

            sd.Add(new EmployeeID(5), new Person("中國", "諸葛亮", 24));

            sd.Add(new EmployeeID(1), new Person("美國", "豪威爾", 40));

            sd.Add(new EmployeeID(0),new Person("美國", "奧巴馬", 40));

            sd.Add(new EmployeeID(210), new Person("朝鮮", "金三胖", 40));

            sd.Add(new EmployeeID(80), new Person("印度", "印度阿三", 40));

             

            foreach (var item in sd)

            {

                Console.WriteLine(item.Key.ID+","+item.Value.Name);//鍵,正序排序

            }

            Console.ReadKey();

        }

    }

    public class EmployeeID : IComparable<EmployeeID>

    {

        public int ID { get; private set; }

        public EmployeeID(int id)

        {

            this.ID = id;

        }

 

        public int CompareTo(EmployeeID other)

        {

            return ID.CompareTo(other.ID);

        }

    }

    public class Person

    {

        public string Country { get; private set; }

        public string Name { get; private set; }

        public int Age { get; private set; }

        public Person(string country, string name, int age)

        {

            this.Country = country;

            this.Name = name;

            this.Age = age;

        }

 

    }

}

注意:SortedList類使用的內存比SortedDictionary類少,SortedDictionary類在插入和刪除未排序的數據時比較快.

 

 

 

詳細分析SOrtedListSortedDictionary類的不同,SortedList內部用數組保存,只能算是有序線性表,SortedSictionary的內部結構是紅黑樹(這是一種數據結構,不懂得自己去百度).

 

SortedDictionary內部結構是紅黑樹,紅黑樹的平衡二叉樹的一種,SortedList是有序線性表,內部結構是Array,運用了二分查找法提高效率.從兩者查找,插入,刪除操作的時間復雜度來看,都為O(LogN),分辨不出優劣,但內部結構的不同導致了實際操作的性能差異.

 

SortedListSortedDictionary性能比較----插入

由於SortedList用數組保存,每次進行插入操作時,首先用二分查找發找到相應的位置,得到位置以后,SortedList會把該位置以后的值依次往后移動一個位置,空出當前位,再把值插入,這個過程用到了Array.Copy方法,而調用該方法是比較損耗性能的,代碼如下:

private void Insert(int index,TKey key,TValue value)

{

...

if(index<this._size)

{

Array.Copy(this.keys.index,this.keys,index+1,this._size-index);

Array.Copy(this.values,index,this.values,index+1,this._size-index);

}

...

}

SortedDictionary在添加操作時,只會根據紅黑樹的特性,旋轉節點,保持平衡,並沒有對Array.Copy的調用.

 

測試代碼:循環一個int,容量為100000的隨機數組,分別用SortedListSortedDictionary添加.

 

結論:在大量添加操作的情況下,SortedDictionary性能優於DortedList.

 

 

SortedListSortedDictionary性能比較----查詢

兩者的查詢操作中,事件復雜度都為O(LogN),且源碼中也沒有額外的操作造成性能損失.

經過測試得出:兩者在循環10W次的情況下,僅僅相差幾十毫秒,可以看出兩者的查詢操作性能相差不大.

 

SortedListSortedDictionary性能比較----刪除

從添加操作的案例可以看出,由於SortedList內部使用數組進行存儲數據,而數組本身的局限性使得SortedList大部分的添加操作都要滴啊用Array.Copy方法,從而導致了性能的損失,這種情況同樣存在於刪除操作中.所以得出了:在大量刪除操作的情況下是,SortedDictionary的性能優於SortedList.

 

總結:SortedDictionary內部用紅黑樹存儲數據,SortedList用數組存儲數據,兩者的查詢效率差不多,但由於數組本身的限制,在大量添加刪除操作的情況下,SortedDictionary的性能優於SortedList.

 


免責聲明!

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



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