zoukankan      html  css  js  c++  java
  • 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.

  • 相关阅读:
    Linq to OBJECT延时标准查询操作符
    LINQ to XML
    动态Linq(结合反射)
    HDU 1242 dFS 找目标最短路
    HDu1241 DFS搜索
    hdu 1224 最长路
    BOJ 2773 第K个与m互质的数
    ZOJ 2562 反素数
    2016 ccpc 杭州赛区的总结
    bfs UESTC 381 Knight and Rook
  • 原文地址:https://www.cnblogs.com/android-blogs/p/6609944.html
Copyright © 2011-2022 走看看