来源:百度文库 编辑:九乡新闻网 时间:2024/05/03 01:57:14
映射和多重映射基于某一类型Key的键集的存在,提供对T类型的数据进行快速和高效的检索。对map而言,键只是指存储在容器中的某一成员。Map不支持副本键,multimap支持副本键。Map和multimap对象包涵了键和各个键有关的值,键和值的数据类型是不相同的,这与set不同。set中的key和value是Key类型的,而map中的key和value是一个pair结构中的两个分量。
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
Map是标准关联式容器(associative container)之一,一个map是一个键值对序列,即(key ,value)对。它提供基于key的快速检索能力,在一个map中key值是唯一的。map提供双向迭代器,即有从前往后的(iterator),也有从后往前的(reverse_iterator)。
map要求能对key进行<操作,且保持按key值递增有序,因此map上的迭代器也是递增有序的。如果对于元素并不需要保持有序,可以使用hash_map。
map中key值是唯一的,如果马匹中已存在一个键值对(昵称,密码):("skynet",407574364),而我们还想插入一个键值对("skynet",472687789)则会报错(不是报错,准确的说是,返回插入不成功!)。而我们又的确想这样做,即一个键对应多个值,幸运的是multimap可是实现这个功能。 //先举一个小例子,
找出数组中重复次数最多的元素并打印,能否给出更优的方案 - public class Problem_3 {
-
- //先快速排序后循环查找 O( n*log2(n) + n )
- public static void find1(int[] arr){
-
- QuickSort.sort(arr);
-
-
- int max = arr[0];
- int pre=1;
- int now=1;
-
- for(int i=0;i<(arr.length-1);i++){
-
- if(arr[i]==arr[i+1])
- now++;
- else {
- if(now>=pre){
- pre=now;
- now=1;
- max=arr[i];
- }
- }
- }
-
-
-
- }
-
- //嵌套循环查找 O(n*n)
- public static void find2(int[] arr){
-
-
- int pre=0;
- int max=arr[0];
-
- for(int i=0;i
- int now=0;
- for(int j=0;j
-
- if(arr[i]==arr[j]) {
- now++;
- }
- }
-
- if(now>=pre){
- max=arr[i];
- pre=now;
- }
-
-
- }
-
-
-
- }
-
- //通过 Hash 方式
- public static void find3(int[] arr){
- HashMap hm=new HashMap();
- for(int i=0;i
- if(hm.containsKey(arr[i])) {
- int count=hm.get(arr[i]);
- hm.put(arr[i], ++count);
-
- }else{
- hm.put(arr[i],1);
- }
- }
-
- Iterator> it=hm.entrySet().iterator();
- int pre=0;
- int max=arr[0];
- while(it.hasNext()) {
- Entry en=it.next();
- int key=en.getKey();
- int val=en.getValue();
- if(val>pre){
- pre=val;
- max=key;
- }
-
- }
-
-
-
- }
- public static void main(String args[]){
-
- //数据量800 重复元素多,查找时候分别是: 46 3680 195
- int arr2[]={0,1,2, .....
- ,0,1,2,3,6,7,8,9};
-
- //数据量800 重复元素少,查找时间分别是 82 3727 360
- int arr[]={0,0,0,11,12,13,14,5,6 ......
- ,51,52,53,,728,29,730,731,3,794,95,796,797,798,799};
-
-
-
- long start,end;
-
- start=System.currentTimeMillis();
- for(int i=0;i<1000;i++) find1(arr);
- end=System.currentTimeMillis();
- System.out.println(end-start);
-
- start=System.currentTimeMillis();
- for(int i=0;i<1000;i++) find2(arr);
- end=System.currentTimeMillis();
- System.out.println(end-start);
-
-
- start=System.currentTimeMillis();
- for(int i=0;i<1000;i++) find3(arr);
- end=System.currentTimeMillis();
- System.out.println(end-start);
-
- }
- }
大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。
测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下:
hash_map(10万) map(10万) hash_map(20万) map(20万) hash_map(30万) map(30万)
添加 93 47 156 94 203 172
遍历 16 15 16 16 16 15
查找 0 0 32 31 31 32
删除 8422 32 33765 63 76016 78
通过上面的数据比较,我们很容易发现hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍;从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。但我们使用map、hash_map一般都用于查找和遍历较多,而且上述测试数据也不能反映出这两方面的性能差距,于是继续对查找和遍历进行了性能测试,得到具体数据如下,时间单位仍为毫秒:
hash_map(100万) map(100万) hash_map(200万) map(200万) hash_map(300万) map(300万)
遍历 94 31 203 32 297 47
查找 94 234 188 531 281 875
通过上面的测试数据可以得出结论是map的遍历性能高于hash_map,而查找性能则相反,hash_map比map要好,数据量越大查找次数越多,表现就越好。
两大组测试完毕,整体结论也可以得出:一般应用情况下,我们保存的数据不超过100万份,查找的频繁程度不高情况下使用map性能比较好;而保存的数据较多时(超过100万),查找频繁时使用hash_map的性能就高于map了。
测试环境具体如下:
操作系统:Windows XP Professional (5.1, Build 2600) Service Pack 3 (2600.xpsp_sp3_gdr.080814-1236)
编译环境:Microsoft Visual C++ 2005 55603-007-4000003-41525
处理器:Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz (2 CPUs)
内存:2044MB RAM,
另外,整个测试仅使用物理内存,而没有虚拟内存,使用Release版本直接在控制台中运行,而没有在IDE中运行,避免影响性能;且对于较短时间计时,少于20毫秒以下可能不准确。
1.map介绍 使用map得包含map类所在的头文件: #include