map、hash_map、迭代器

来源:互联网 发布:网络销售平台策划方案 编辑:程序博客网 时间:2024/05/20 01:08

1. hash_map和map的区别在哪里?

构造函数。hash_map需要hash函数,等于函数;map只需要比较函数(小于函数).
存储结构。hash_map采用hash表存储,map一般采用红黑树(RB Tree)实现。因此其内存数据结构是不一样的。

2. 什么时候需要用hash_map,什么时候需要用map?

选用map还是hash_map,关键是看关键字查询操作次数,以及你所需要保证的是查询总体时间还是单个查询的时间。

如果是要很多次操作,要求其整体效率,那么使用hash_map,平均处理时间短。

如果是少数次的操作,那么使用平均处理时间相对较慢、单次处理时间恒定的map,考虑整体稳定性应该要高于整体效率,因为前提在操作次数较少。

3.迭代器

<iterator> 中定义了迭代器得使用方法,主要得模版类有:

插入迭代器

插入迭代器是一种迭代器适配器,带有一个容器参数,并生成一个迭代器,用于在指定的容器中插入元素。通过插入迭代器赋值时,迭代器将会插入一个新的元素。C++语言提供了三种插入器,其差别在于插入元素的位置不同:

back_inserter,创建使用push_back实现插入的迭代器,其使用一个对象作为实参将一个新元素插入到容器得后端
front_inserter的操作类似于back_inserter:该函数将创建一个迭代器,调用它所关联的基础容器的push_front成员函数代替赋值操作。
注意:只有当容器提供push_front操作时,才能使用front_inserter。在vector或其他没有push_front运算的容器上使用front_inserter,将产生错误。
inserter使用insert实现插入操作,inserter还带有第二个实参:指向插入起始位置的迭代器,inserter总是在它的迭代器参数所标明的位置前面插入新元素。
流迭代器
虽然iostream类型不是容器,但标准库同样提供了在iostream对象上使用的迭代器:istream_iterator用于读取读入流,而ostream_iterator用于写输出流。这些迭代器将它们所对应的流视为特定类型的元素序列。使用流迭代器时,可以用泛型算法从流对象中读数据(或将数据写到流对象中)。
istream_iterator<T> in(strm);创建从输入流strm中读取T类型对象的istream_iterator对象,strm是一个输入流istream_iterator<T> in;istream_iterator对象的超出末端迭代器ostream_iterator<T> out(strm);创建将T类型的对象写到输出流strm的ostream_iterator对象ostream_iterator<T> out(strm, delim);创建将T类型的对象写到输出流strm的ostream_iterator对象,在写入过程中使用delim作为元素的分隔符。delim是以空字符结束的字符数组
   流迭代器只定义了最基本的迭代器操作:自增、引用和赋值。此外,可比较两个istream迭代器是否相等(或不等)。而ostream迭代器则不提供比较运算。
流迭代器的限制:
(1)不可能从ostream_iterator对象读入,也不可能写到istream_iterator对象中;
(2)一旦给ostream_iterator对象赋了一个值,写入就提交了。赋值后,没有办法再改变这个值。此外,ostream_iterator对象中每个不同的值都只能正好输出一次。
(3)ostream_iterator没有->操作符。
测试:

#include<iostream>
#include <vector>
#include <iterator>
using namespacestd;
int main(){
    istream_iterator<int> in_iter(cin);
    istream_iterator<int>eof;
    
//vector<int> vec(in_iter, eof); //do the same work as following loop
    vector<int> vec;
    while (in_iter!=eof)
         vec.push_back(*in_iter++); //*in_iter可以取出输入流中得元素   
    vector<int>::const_iterator it = vec.begin();
    for(; it!= vec.end();++it)
        cout<<*it<<endl;
    
    return 0;
}

***********

#include<iostream>
#include <iterator>
using namespacestd;
int main(){
    ostream_iterator<string> out_iter(cout,""n");
    istream_iterator<string> in_iter(cin),eof;
    while (in_iter!=eof)
        *out_iter++=*in_iter++;
    return 0;
}

反向迭代器
反向迭代器是一种反向遍历容器的迭代器。也就是,从最后一个元素到第一个元素遍历容器。反向迭代器将自增(和自减)的含义反过来了:对于反向迭代器,++运算将访问前一个元素,而--运算则访问下一个元素。
(1)反向迭代器需要使用自减操作符:标准容器上的迭代器(reverse_iterator)既支持自增运算,也支持自减运算。但是,流迭代器由于不能反向遍历流,因此流迭代器不能创建反向迭代器。
(2)可以通过reverse_iterator::base()将反向迭代器转换为普通迭代器使用,从逆序得到普通次序。
测试:
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
using namespace std;
int main() {
    string str = "this 'sentence' is a test";
    cout<<str<<endl;
   
    string::iterator it1 = find(str.begin(), str.end(), '"'');
    string::iterator it2 = find(++it1, str.end(), '"'');
    cout<<string(it1, it2)<<endl;
   
    string::reverse_iterator rit1 = find(str.rbegin(), str.rend(), '"'');
    string::reverse_iterator rit2 = find(++rit1, str.rend(), '"'');
    cout<<string(rit1, rit2)<<endl;
    cout<<string(rit2.base(), rit1.base())<<endl;
    getchar();
    return 0;
}
 
不同的迭代器支持不同的操作集,而各种算法也要求相应的迭代器具有最小的操作集。因此,可以将算法的迭代器分为下面五类:
输入迭代器
(input iterator)
读,不能写。支持的操作集:==, !=, 前缀++, 后缀++, *, ->。例如,find, accumulate算法要求这类迭代器。输出迭代器
(output iterator)
写,不能读。支持的操作集:前缀++, 后缀++, *(只能出现在赋值运算的左操作数上)。推出迭代器要求每个迭代器必须正好写入一次。例如,ostream_iterator是输出迭代器,copy算法使用这类迭代器。前向迭代器(forward iterator)读和写,支持输入迭代器和输出迭代器提供的所有操作,还支持对同一个元素的多次读写。例如,replace算法需要这种迭代器。双向迭代器(bidirectional iterator)读和写,除了支持前向迭代器的所有操作,还支持前缀--和后缀--,即支持双向遍历容器。例如,reverse算法要求这类迭代器。标准库容器中提供的迭代器都至少达到双向迭代器的要求。随机访问迭代器(random-access iterator)读和写。提供在常量时间内访问容器任意位置的功能。支持完整的迭代器操作集:1)关系运算:==, !=, <, <=, >, >=;2)算术运算:it + n, it - n, it += n, it -= n以及it1 - it2;3)下标运算:it[n],等价于*(it + n)。需要随机访问迭代器的泛型算法包括sort算法。例如,vector, deque, string迭代器是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。
   除了输出迭代器,其他类别的迭代器形成了一个层次结构:需要低级类别迭代器的地方,可使用任意一种更高级的迭代器。例如,对于需要输入迭代器的算法,可传递前向、双向或随机访问迭代器调用该算法。而反之则不行。注意:向算法传递无效的迭代器类别所引起的错误,无法保证会在编译时被捕获到。
   map, set, list类型提供双向迭代器,而string, vector和deque容器上定义的迭代器都是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。istream_iterator是输入迭代器,ostream_iterator是输出迭代器。
   另外,虽然map和set类型提供双向迭代器,但关联容器只能使用这部分算法的一个子集。因为关联容器的键是const对象。因此,关联容器不能使用任何写序列元素的算法。只能使用与关联容器绑在一起的迭代器来提供用于读操作的实参。因此,在处理算法时,最好将关联容器上的迭代器视为支持自减运算的输入迭代器,而不是完整的双向迭代器。
原创粉丝点击