这些天都在学C#,正好看到集合部分想到了一个比较形象的点子来解释各种集合以及性能的比较。这个模版现在是1.0版本需要不断总结以便能够形象的描述程序中各种数据结构的模式。
首先给大家介绍一个神奇的讲解载体 一根 PVC管子。
把集合先具体化一个pvc管子。
对于我现在学到的集合有这几种
List,Set,Map,Queue.(这个是Java)。
或者
列表,队列,栈,链表,有序列表,字典,集,可观察集合,位数组,并发集合。说实话C#只是把名字改了一改,如果从物理逻辑来看基本是一样的。
为了大家方便我们先以Java的集合分类来讲起,不同语言上名字上的区别我会给大家对号入座列出一个表。
我们先说 List 中的ArryList。
这些小黄人相当于存储的元素。我们思考下add 和 remove 以及sort,find,insert操作。
O(1)代表 所需时间不会随着元素的增加而增加,1个元素与100个元素几乎相等。
O(n)代表 所需时间会随着元素的增加而增加,而且每个元素增加的时间量都相同是线性增加。
O(log n)代表 所需时间随着元素的增加而增加,而且每个元素的时间量都是不同的是曲线增加。(也就是说你增加一个元素或者要比前一个元素还要多的时间)
首先ArrayList add操作,如果我们拿来的管子正好有空我们如果有add就往后面加就可以了,list容量不会改变,但是如果水管以及满了那么必须改变大小(重新搞根水管)才能放的下,所以O(1)或者O(n)。
remove操作,如果我们剔除一个小黄人,这样就有一个位置是空的,我们list中不准许前面空着,所以后面的index都会往前面挪动,如果后面的元素越多挪动的次数就越多。所以是 O(n)。
sort操作,排序操作至少是 元素越多时间曲线增加,如果不碰巧位置都需要变化那么时间将超过曲线。O (n logn),最坏的情况是 O(n^2)。排序时间的算法是最复杂的一种,需要理解一些内存中的逻辑和数学表达。
insert操作,同理remove 所以是 O(n)。
find操作,不需要解释,小黄人越多越不好找 O(n)。
再者是队列
首先Queue add操作,如果我们拿来的管子正好有空我们如果有add就往后面加就可以了,Queue容量不会改变,但是如果水管以及满了那么必须改变大小(重新搞根水管)才能放的下,所以O(1)或者O(n)。
remove操作,如果我们剔除一个小黄人,这样就有一个位置是空的,由于地心引力(暂时想不出其他名词了)上面的那些小黄人直接做电梯下来了,所以移除操作都是一样的时间O(1);
sort操作,打进楼层中的小黄人不能排序。--太黑找不到怎么排序
insert操作,打进楼层中的小黄人不能排序。--太黑找不到怎么插入
find操作,打进楼层中的小黄人不能排序。--太黑找不到
首先Stack add操作,如果我们拿来的管子正好有空我们如果有add就往后面加就可以了,Stack 容量不会改变,但是如果水管以及满了那么必须改变大小(重新搞根水管)才能放的下,所以O(1)或者O(n)。
remove操作,如果我们剔除一个小黄人,这样就有一个位置是空的,由于地心引力(暂时想不出其他名词了)上面的那些小黄人直接做电梯下来了,所以移除操作都是一样的时间O(1);
sort操作,打进楼层中的小黄人不能排序。--太黑....同上
insert操作,打进楼层中的小黄人不能排序。--太黑....同上
find操作,打进楼层中的小黄人不能排序。--太黑....同上
再来说LinkedList:
LinkedList add操作,O(1),添加一个小黄人都是加跟红线和小黄人的操作,这里想象着这个PVC管就算不存在,我还有红线连着,所以更集合中元素的数量无关。O(1)
remove操作,同理于add
sort操作,不支持。
insert操作,同理于add
find操作,不需要解释,小黄人越多越不好找 O(n)。
接下来就是Set HashSet:set是不能包含重复元素的。
HashSet:add操作,O(1),添加一个小黄人如果不是重置整个集合插入都是O(1).如果重置整个集合O(n).
remove操作,由于只于HashCode现关联删除操作并不需要重新排序集合,所以无论多少只是一个断链的过程。O(1).
insert操作,同理于add
sort操作,不支持。
find操作,不支持。
SortedSet: 同上。
最后是Map
map最常见的存储方式也是根据hash值来存储以HashMap为例(C#的Dictionary不知道是否更具Hash来存储):
HashMap/Dictionary:add操作,O(1),添加一个小黄人如果不是重置整个集合插入都是O(1).如果重置整个集合O(n).
remove操作,由于只于HashCode现关联删除操作并不需要重新排序集合,所以无论多少只是一个断链的过程。O(1).
insert操作,不支持。
sort操作,不支持。
find操作,不支持。
备注:看到资料中这样说,“C++ Map实现逻辑的是红黑树方式,而Dictionary实现逻辑是hashcode”,我觉得Dictionary如果要对应上HashMap应该需要2个都实现才对。
http://zhidao.baidu.com/link?url=YW1D-Duso2MSQY5jzV1wJo6Qe72SnqqCv6fUqS3ZRBj_d_q8K9_qiYbzlK_oM2bEYnrFCu9tm5ZL4V0sZ1O9HyMvTeIr2tXSadUhmrMEfu7.
由于刚刚开始学习C#所以很多理解上或许有些偏差,请各位老鸟路过的时候尽情指正,小菜不胜感激。
从许多书上看,ArrayList的查找要比LinkedList要优秀。上图中的效率表达方式希望大家理解正确,ArarryList O(1) 与 LinkedList O (1)不能理解为一样的时间,只能理解为两种集合每种集合数量多少与效率都是没关系的,但是就find来说,ArrayList的find比LinkedList的find要效率很多,不过如果对LinkedList加上索引不知道能否媲美ArrayList。