C++ primer 第十一章复习

简介: C++ primer 第十一章复习

C++ primer 第十一章

11.1 使用关联容器

关联容器:元素是按关键字来保存和访问的


顺序容器:元素是按它们在容器中的位置来顺序保存和访问的



使用关联容器

使用 MAP


/*
  统计每个数字在输入中出现的次数
*/
std::map<int, size_t> word_cout;
int number;
while (std::cin >> number){
++word_cout[number];
}
for (const auto& w : word_cout){
  std::cout << w.first << " occurs " << w.second << " times" << std::endl;
}

使用 SET


/*
  只统计不在set里面的数字
*/
std::map<int, size_t> word_cout;
std::set<int> set1 = { 0, 1, 4, 9, 2, 3, 1 };
int number;
while (std::cin >> number){
if (set1.find(number) == set1.end()){
++word_cout[number];
    }
}
for (const auto& w : word_cout){
  std::cout << w.first << " occurs " << w.second << " times" << std::endl;
}

11.2 关联容器概述

map 或 set 中的关键字必须是唯一的


关联容器初始化



初始化 multimap 或 multiset


//定义一个有20个元素的vector,保存0-9每个整数的两个拷贝
std::vector<int> ivec;
for (std::vector<int>::size_type i =0; i !=10; ++i){
  ivec.push_back(i);
  ivec.push_back(i);
}
std::set<int> set1(ivec.begin(), ivec.end());
std::multiset<int> set2(ivec.begin(), ivec.end());
std::cout << ivec.size() << std::endl; //20
std::cout << set1.size() << std::endl; //10
std::cout << set2.size() << std::endl; //20

关键字要求


有序容器:map,multimap,set,multiset 关键字必须定义元素的比较方法



如果一个类型定义了严格弱序的 < 运算符,则可以用作关键字类型


struct Demo{
  int number;
};
bool compareDemo(const Demo& demo1, const Demo& demo2){
  return demo1.number > demo2.number;
}
int main(){
  std::multiset<Demo, decltype(compareDemo)*> demoSet(compareDemo);
}

函数指针使用记录


struct HashHelper{
public:
  static int INT_INT(void* valueBuffer) {
    return 1;
  }
};
typedef int(*GetHashCode)(void* valueBuffer);
struct Hash{
  Hash(){
    caseTypeFillFuncPtrs(1);
  }
  void caseTypeFillFuncPtrs(int x){
    switch (x) {
      case 1:m_dim_funcPtrs.emplace_back(&HashHelper::INT_INT);
    }
  }
  int operator() const{
    int totalHashCode =0;
    void* val =0;
for (int i =0; i < 5; ++i){
      totalHashCode += m_dim_funcPtrs[i](val);
    }
  }
private:
  std::vector<GetHashCode> m_dim_funcPtrs;
}

pair 类型


pair 是一个用来生成特定类型的模板,默认对数据成员值初始化


std::pair<std::string, std::string> anon;
std::pair<std::string, size_t> word_count;
std::pair<std::string, std::vector<int>> line;
std::pair<std::string, std::string> author = {"James","Joyce"};

pair 的数据成员时 public 的,两个成员分别是 first 和 second


std::cout << w.first << " occurs " << w.second << " times" << std::endl;

此处,w 是指向 map 中某个元素的引用,map 的元素时是 pair


创建 pair 对象的函数


std::pair<std::string, int> process(){
  //return std::pair<std::string, int>();
  std::vector<std::string> v1;
  return std::make_pair(v1.back(),v1.size());
}

11.3 关联容器操作


std::set<std::string>::key_type v1; //string
std::set<std::string>::value_type v2; //string
std::map<std::string,int>::value_type v3; //pair<const std::string,int>
std::map<std::string, int>::key_type v4; //string
std::map<std::string, int>::mapped_type v5; //int

关联容器迭代器


一个 map 的 value_type 是一个 pair,可以改变 pair 的值,但不能改变关键字成员的值


std::map<int, size_t> word_cout;
//指向word_cout中一个元素的迭代器
auto map_it = word_cout.begin();
//*map_it是指向pair<const int, size_t>对象的引用
std::cout << map_it->first; //打印此元素的关键字
std::cout << map_it->second; //打印此元素的值
map_it->first =1; //错误,关键字是 const 的
++map_it->second; //正确

set 的迭代器是 const 的


std::set<int> set1 = { 0, 1, 2, 3, 4 };
std::set<int>::iterator set_it = set1.begin();
if (set_it != set1.end()){
  *set_it =42;//错误,set的关键字是只读的
  std::cout << *set_it << std::endl;
}

当迭代器遍历一个map,multimap,set,multiset 迭代器按关键字升序遍历元素



添加元素

删除元素

Map 下标操作


map 下标操作和其它下标操作不同在于返回类型。通常解引用一个迭代器返回的类型和下标运算符返回类型一样。但对于 map,进行下标操作时,会获得一个 mapped_type 对象,但当解引用时会得到一个 value_type 对象


std::map<std::string,size_t> word_cout;
//插入一个关键字为 Anna 的元素,关联值并进行初始化,然后将 1 赋给它
word_cout["Anna"] =1;


下标运算符可能插入一个新元素,因此只能对非 const map 使用下标


访问元素


set<int> iset = {0,1,2,3,4};
iset.find(1); //返回一个迭代器,指向 key ==1 的元素
iset.find(11); //返回一个迭代器,指向 iset.end()
iset.count(1); // 1iset.count(11); // 0

在 multimap 中查找元素


具有相同关键字的这些元素在容器中会相邻存储



如果 lower_bound 和 upper_bound 返回相同的迭代器,则给定关键字不在容器中


for(auto beg = authors.lower_bound(search_item), end =  authors.upper_bound (search_item);beg != end;++beg){
    cout << beg -> second << endl;
}
//pos保存迭代器对,表示和关键字匹配的元素范围
for(auto pos = authors.equal_range(search_item);pos.first != pos.second;++pos.first){
    cout << pos.first -> second << endl;
}

11.4 无序容器

无序容器:不使用比较运算符来组织元素,而是使用哈希函数和关键字类型的 == 运算符


//统计出现次数,但单次不按字典排序
unorder_map<string,size_t> word_count;
string word;
while(cin>>word){
++word_count[word];
}
for(const auto& w : word_count){
    cout << w.first << "--" w.second << endl;
}


无序容器默认情况下:


使用关键字类型的 == 运算符比较元素


使用一个 hash<key_type> 类型的对象来生成每个元素的哈希值


标准库为内置类型(包含指针),string,智能指针提供了哈希模板


不能直接定义自定义类型为无序容器的关键字类型(需重写哈希函数和比较方法)


相关文章
|
5月前
|
编译器 C++
c++primer plus 6 读书笔记 第十章 对象和类
c++primer plus 6 读书笔记 第十章 对象和类
|
5月前
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
|
5月前
|
C++
C++ Primer Plus (第6版)中文版 (使用XMind整理)
C++ Primer Plus (第6版)中文版 (使用XMind整理)
C++ Primer Plus (第6版)中文版 (使用XMind整理)
|
5月前
|
C++
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
|
5月前
|
C++
c++primer plus 6 读书笔记 第十一章 使用类
c++primer plus 6 读书笔记 第十一章 使用类
|
5月前
|
编译器 C++
c++primer plus 6 读书笔记 第八章 函数探幽0
c++primer plus 6 读书笔记 第八章 函数探幽0
|
5月前
|
编译器 vr&ar C++
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
|
5月前
|
SQL 人工智能 算法
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
|
5月前
|
程序员 C++
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
|
5月前
|
存储 IDE 编译器
c++primer plus 6 读书笔记 第九章 内存模型和名称空间
c++primer plus 6 读书笔记 第九章 内存模型和名称空间