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.

  • 相关阅读:
    LeetCode 258. Add Digits
    LeetCode 257. Binary Tree Paths
    LeetCode 周赛 184
    js算法初窥05(算法模式02-动态规划与贪心算法)
    js算法初窥04(算法模式01-递归)
    js算法初窥03(搜索及去重算法)
    js算法初窥02(排序算法02-归并、快速以及堆排序)
    js算法初窥01(排序算法01-冒泡、选择、插入)
    用js来实现那些数据结构16(图02-图的遍历)
    用js来实现那些数据结构15(图01)
  • 原文地址:https://www.cnblogs.com/FinleyJiang/p/7602710.html
Copyright © 2011-2022 走看看