几种常见 容器 比较和分析 hashmap, map, vector, list ...hash table
list支持快速的插入和删除,但是查找费时;
vector支持快速的查找,但是插入费时。
map查找的时间复杂度是对数的,这几乎是最快的,hash也是对数的。
如果我自己写,我也会用二叉检索树,它在大部分情况下可以保证对数复杂度,最坏情况是常数复杂度,而std::map在任何情况下都可以保证对数复杂度,原因是它保证存诸结构是完全二叉检索树,但这会在存诸上牺牲一些时间。
STL 中的 map 内部是平衡二叉树,所以平衡二叉树的性质都具备。查找数据的时间也是对数时间。 vector,在分配内存上一般要比
new 高效的多。
为什么说 hash_map 是对数级的?在不碰撞的情况下,hash_map是所有数据结构中查找最快的,它是常数级的。
如果对问题设计了足够好的hash算法,保证碰撞率很低,hash_map的查找效率无可置疑。
另外,STL的map,它的查找是对数级的,是除hash_map外最高的了,你可以说“也许还有改进余地”,但对于99.9999%的程序员,设计一个比STL
map好的map,我执悲观态度。
STL的map有平衡策略(比如红黑树什么的),所以不会退化,不需要考虑数据本身的分布问题。只不过,如果数据本身是排好序的,用vector或heap会明显的快些,因为它们的访问比较简单。
我想没必要怀疑stl::map的查找效率,影响效率最主要的因素是什么?算法,在查找问题上,有什么算法比RB_tree更好吗?至少现在还没有。不否 认你可以通过自己写代码,设计一个符合你需要的BR—TREE,比stl::map简捷那么一点,但最多也就每次迭代中少一行指令而已,处理十万个数据多 执行十万行指令,这对你重要吗?如果你不是在设计OS像LINUX,没人会关注这十万行指令花的时间。
rb-tree的时间花在了插入和删除上,如果你不是对插入和删除效率要求很高,你没有理由不选择基于rb-tree的stl::map。
大多数程序员写不出比std::map更好的map,这是当然的。然而并不是std::map的所有特性都出现在我们的程序中,自己编写的可以更适合自己的程序,的确会比std::map更快一些。
关于hash_map,它与map的实现机制是不一样的,map内部一般用树来实现,其查找操作是O(logN)的,这个没有争议,我就不多说了。
hash_map的查找,内部是通过一个从key到value的运算函数来实现的,这个函数“只接受key作为参数”,也就是说,hash_map的查找 算法与数据量无关,所以认为它是O(1)级的。来这里的应该都是达人,可以参看《数据结构》。当然,事实总不这样完美,再引一段前面我自已说的话,进一步 说明,以免误会:
-----------------------------------------
在不碰撞的情况下,hash_map是所有数据结构中查找最快的,它是常数级的。
------------------------------------------
注意我的前提:“在不碰撞的情况下”,其实换句话说,就是要有足够好的hash函数,它要能使key到value的映射足够均匀,否则,在最坏的情况下,它的计算量就退化到O(N)级,变成和链表一样。
如果说 hash_map 是所有容器中最慢的,也只能说:“最拙劣的hash函数”会使hash_map成为查找最慢的容器。但这样说意义不大,因为,最凑巧的排列能使冒泡排序成为最快的排序算法。
BS: "对于大型容器而言,hash_map能够提供比map快5至10倍的元素查找速度是很常见的,尤其是在查找速度特别重要的地方.另一方面,如果hash_map选择了病态的散列函数,他也可能比map慢得多. "
ANSIC++在1998年之后就没再有重大改变,并且决定不再向C++标准库中做任何重大的变更,正是这个原因,hash table(包括hash_map)并没有被列入标准之中,虽然它理应在C++标准之中占有一席之地。
虽然,现在的大多数编译平台支持hash table,但从可移植性方面考虑,还是不用hash table的好。
hehe俺也来凑凑热闹。
1.有的时候vector可以替代map
比如key是整数,就可以以key的跨度作为长度来定义vector。
数据规模很大的时候,差异是惊人的。当然,空间浪费往往也惊人。
2.hash是很难的东西
没有高效低碰撞的算法,hash_xxx没有意义。
而对不同的类型,数据集,不可能有优良的神仙算法。必须因场合而宜。
俺有的解决方法是GP,可不是饭型,是遗传编程,收效不错。
你的百万级的数据放到vector不大合适。因为vector需要连续的内存空间,显然在初始化这个容器的时候会花费很大的容量。
使用map,你想好了要为其建立一个主键吗?如果没有这样的需求,为什么不考虑deque或者list?
map默认使用的是deque作为容器。其实map不是容器,拿它与容器比较意义不大。因为你可以配置它的底层容器类型。
如果内存不是考虑的问题。用vector比map好。map每插入一个数据,都要排序一次。所以速度反不及先安插所有元素,再进行排序。
用 binary_search对已序区间搜索,如果是随机存取iterator,则是对数复杂度。可见,在不考虑内存问题的情况下,vector比map
好。
如果你需要在数据中间进行插入,list 是最好的选择,vector 的插入效率会让你痛苦得想死。
涉及到查找的话用map比较好,因为map的内部数据结构用rb-tree实现,而用vector你只能用线性查找,效率很低。
stl还提供了 hash容器,理论上查找是飞快~~~。做有序插入的话vector是噩梦,map则保证肯定是按key排序的,list要自己做些事情。
HASH类型的查找肯定快,是映射关系嘛,但是插入和删除却慢,要做移动操作, LIST类型的使链式关系,插入非常快,但是查找却费时,需要遍历~~
, 还是用LIST类型的吧,虽然查找慢点,
先快速排序,然后二分查找,效率也不低
几种常见 容器 比较和分析 hashmap, map, vector, list ...hash table的更多相关文章
- Java 容器源码分析之 Map
ava.util 中的集合类包含 Java 中某些最常用的类.最常用的集合类是 List 和 Map.List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建 ...
- 【转】【java源码分析】Map中的hash算法分析
全网把Map中的hash()分析的最透彻的文章,别无二家. 2018年05月09日 09:08:08 阅读数:957 你知道HashMap中hash方法的具体实现吗?你知道HashTable.Conc ...
- (转)hashmap hashtable 的区别 Hash table 内部的数据结构
转自:http://www.cnblogs.com/carbs/archive/2012/07/04/2576995.html Hashtable 和 HashMap 做为 Map 的基本特性 两者都 ...
- (转)App工程结构搭建:几种常见Android代码架构分析
关于Android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角度,看到整齐的代码,优美的分层总是一种舒服的享受的. 从艺术的角度看,其实我们是在追求一种美. 本文先分析几个当 ...
- C++ STL中常见容器的时间复杂度和比较和分析
C++ STL中常见容器的时间复杂度 map, set, multimap, and multiset 上述四种容器采用红黑树实现,红黑树是平衡二叉树的一种.不同操作的时间复杂度近似为: 插入: O( ...
- JAVA几种常见的编码格式(转)
简介 编码问题一直困扰着开发人员,尤其在 Java 中更加明显,因为 Java 是跨平台语言,不同平台之间编码之间的切换较多.本文将向你详细介绍 Java 中编码问题出现的根本原因,你将了解到:Jav ...
- Java 容器源码分析之HashMap多线程并发问题分析
并发问题的症状 多线程put后可能导致get死循环 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题.后来,我们的程序性能有问题,所以需要变成多 ...
- SQL Server 存储过程中处理多个查询条件的几种常见写法分析,我们该用那种写法
本文出处: http://www.cnblogs.com/wy123/p/5958047.html 最近发现还有不少做开发的小伙伴,在写存储过程的时候,在参考已有的不同的写法时,往往很迷茫,不知道各种 ...
- 几种常见的JavaScript混淆和反混淆工具分析实战
几种常见的JavaScript混淆和反混淆工具分析实战 xiaix2016-03-05+8共1195751人围观 ,发现 5 个不明物体WEB安全 信息安全常被描述成一场军备竞赛,白帽与黑帽,渗透测试 ...
随机推荐
- GitLab服务器搭建及配置
一.服务器环境 操作系统:CentOS release 6.5 (Final) GitLab版本: GitLab-shell:2.0.1 Ruby version: ruby 2.1.2p95 (20 ...
- linux下bom头导致的php调用php接口 返回的json字符串 无法转成 数组,即json字符串无法解码的问题
今天很是郁闷,写了一个php接口,返回的是标准的json字符串,但是调用的php 就是无法json_decode(),返回错误码为4,最后终于找到原因,原来是蒙一个文件中有bom头,最后采用一个命令 ...
- uva 10820
/* 交表 _________________________________________________________________________________ #include < ...
- glusterfs 内存管理方式
glusterfs中的内存管理方式: 首先来看看glusterfs的内存管理结构吧: struct mem_pool { struct list_head list; int hot_count; i ...
- iOS_Quartz2D之涂鸦板
响应者对象:继承了UIResponder的对象 触摸事件:一根或多根手指: 开始触摸: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent ...
- 【亚瑟士 ASICS 系列】
[新配色 36-44] [亚瑟士 黑薄荷 大工厂流线 36-44] [亚瑟士 阿斯克斯 星空 水洗丹宁 36-44] [亚瑟士 阿斯克斯 经典爆 鼠尾草 36-44] [亚瑟士 ASICS Gel S ...
- 在树莓派(Raspberry Pi)上编译安装更新版本的Python
Raspiban Wheezy上预装的Python3版本是3.2.3,本文将介绍升级到3.4.3的方法. 此文也适用于安装其它版本(比如最新版本)的Python. 我用的是B+型的树莓派,装的系统是2 ...
- 详细解说Java Spring的JavaConfig注解 【抄】
抄自: http://www.techweb.com.cn/network/system/2016-01-05/2252188.shtml @RestController spring4为了更方便的支 ...
- Disque
Disque是一个内存储存的分布式任务队列实现, 它由 Redis 的作者 Salvatore Sanfilippo (@antirez)开发, 目前正处于预览版(alpha)阶段. 本文档将对 Di ...
- break,continue的使用
break,continue 使用break命令允许跳出所有循环下面的例子中,脚本进入死循环直至用户输入数字大于5.要跳出这个循环,返回到shell提示符下,就要使用break命令. #!/bin/b ...