C++ map容器学习笔记

文章目录

map

初始化

  • 创建一个key=stringvalue=int的map空容器。
#include <map>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values;
    return 0;
}
  • 使用初始化列表初始化map容器。
#include <map>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values {{"A", 1}, {"B", 2}};
    return 0;
}
  • 使用make_pair()初始化map容器。
#include <map>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values {std::make_pair("A", 1), std::make_pair("B", 2)};
    return 0;
}

添加元素

  • 使用make_pair()结合insert()函数插入元素。
#include <map>
#include <iostream>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values {std::make_pair("D", 1), std::make_pair("C", 2)};

    auto add_el = std::make_pair("B", 3);
    map_values.insert(add_el);
    map_values.insert(std::make_pair("A", 4));

    for(auto pair_data : map_values) {
        std::cout << pair_data.first << "  " << pair_data.second << std::endl;
    }

    return 0;
}
// 输出结果
// A  4
// B  3
// C  2
// D  1

从输出结果中可以看出,map容器的顺序是按照key的升序排列的,并不是插入的顺序。

  • insert()函数的返回值是一个pair对象,该pair对象并不仅仅刚刚插入的元素数据。pair.first是刚刚要插入的元素pair.second插入的结果
#include <map>
#include <iostream>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values {std::make_pair("D", 1), std::make_pair("C", 2)};

    auto add_el = std::make_pair("B", 3);
    map_values.insert(add_el);
    map_values.insert(std::make_pair("A", 4));

    auto insert_data = map_values.insert(std::make_pair("A", 5));

    std::cout << "insert = " << insert_data.first->first << "  " << insert_data.first->second << std::endl;
    std::cout << "insert result = " << std::boolalpha << insert_data.second << std::endl;

    return 0;
}
// 输出结果
// insert = A  4
// insert result = false
  • 通过emplace()直接在map容器中构造新元素,从而避免复制移动操作。
#include <map>
#include <iostream>
#include <string>

class Person {
public:
    Person(int _age, std::string _name) {
        age = _age;
        name = _name;
    }

    bool operator < (const Person & _person) const {
        return _person.age < age;
    }

private:
    int             age;
    std::string     name;
};

int main(int argc, char * argv[]) {
    std::map<Person, int> map_values;
    map_values.emplace(Person{1, "S"}, 10);
    return 0;
}

代码中使用类对象作为key值,这种方式需要类对象提供operator < ()的重载。

访问元素

  • 使用at(key)的方式访问数据,如果不存在会抛出out_of_range异常。
#include <map>
#include <string>
#include <iostream>

class Person {
public:
    Person(int _age, std::string _name) {
        age = _age;
        name = _name;
    }
    bool operator < (const Person & _person) const {
        return _person.age < age;
    }
private:
    int             age;
    std::string     name;
};

int main(int argc, char * argv[]) {
    std::map<Person, int> map_values;
    map_values.emplace(Person{1, "S"}, 10);
    Person p = {2, "S"};
    try {
        auto value = map_values.at(p);
        std::cout << value << std::endl;
    } catch (const std::out_of_range & e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}
// 输出结果
// invalid map<K, T> key
  • 使用[key]的方式访问数据,如果不存在会添加该元素。
#include <map>
#include <string>
#include <iostream>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values;
    map_values.insert(std::make_pair("A", 10));
    std::cout << map_values.size() << std::endl;

    auto find_value = map_values["A"];
    std::cout << map_values.size() << std::endl;

    find_value = map_values["B"];
    std::cout << map_values.size() << std::endl;

    return 0;
}
  • 通过find(key)访问元素,该方法返回一个指向该元素的迭代器。
#include <map>
#include <string>
#include <iostream>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values;
    map_values.insert(std::make_pair("A", 10));

    auto find_value = map_values.find("A");
    if(find_value != map_values.end())
    	std::cout << find_value->first << ", " << find_value->second << std::endl;
    return 0;
}

删除元素

  • 通过erase(key)函数移除键和对应的值。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values;
    map_values.insert(std::make_pair("A", 1));
    map_values.insert(std::make_pair("B", 2));
    map_values.insert(std::make_pair("C", 3));
    map_values.insert(std::make_pair("D", 4));

    std::cout << map_values.size() << std::endl;

    int value = map_values.erase("A");
    std::cout << value << std::endl;
    
    return 0;
}
  • 通过erase(iterator)函数根据迭代器的位置删除一个元素,返回删除元素所在位置的下个一个元素的迭代器。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values;
    map_values.insert(std::make_pair("A", 1));
    map_values.insert(std::make_pair("B", 2));
    map_values.insert(std::make_pair("C", 3));
    map_values.insert(std::make_pair("D", 4));

    auto next_iter = map_values.erase(map_values.begin());
    std::cout << next_iter->first << std::endl;

    return 0;
}
// 输出结果
// B
  • 通过erase(iterator begin, iterator end)函数移除指定范围的迭代器。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::map<std::string, int> map_values;
    map_values.insert(std::make_pair("A", 1));
    map_values.insert(std::make_pair("B", 2));
    map_values.insert(std::make_pair("C", 3));
    map_values.insert(std::make_pair("D", 4));

    map_values.erase(++map_values.begin(), --map_values.end());

    std::cout << map_values.size() << std::endl;

    return 0;
}

multimap

初始化

  • 通过初始化列表初始化容器。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::multimap<std::string, int> multimap_values = {{"A", 10}, {"A", 15}};
    auto iter = multimap_values.begin();
    while (iter != multimap_values.end()) {
        std::cout << iter->first << ", " << iter->second << std::endl;
        iter++;
    }
    return 0;
}

添加数据

  • 通过insert在指定位置插入元素,和map不同是插入的结果永远是成功的因此返回的只是指向插入元素的迭代器。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::multimap<std::string, int> multimap_values = {{"A", 10}, {"A", 15}};
    auto iter = multimap_values.insert(multimap_values.begin(), std::make_pair("A", 5));
    while (iter != multimap_values.end()) {
        std::cout << iter->first << ", " << iter->second << std::endl;
        iter++;
    }
    return 0;
}
// 输出结果
// A, 5
// A, 10
// A, 15

访问元素

multimap没有提供at(key)或者[key]的访问方式,可以使用find(key)的方法访问,但是该方法返回的是找到元素所在位置的迭代器,由于multimap可以存储重复key值,因此这个访问也不可取。

  • 通过equal_range(key)访问元素,如果找到对应的key则将对应范围内的迭代器全部返回。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::multimap<std::string, int> multimap_values = {{"A", 10}, {"A", 15}};
    multimap_values.insert(multimap_values.begin(), std::make_pair("A", 5));
    multimap_values.insert({{"B", 1}, {"A", 1}, {"B", 5}});

    auto find_result = multimap_values.equal_range("B");
    if (find_result.first != multimap_values.end()) {
        while (find_result.first != find_result.second) {
            std::cout << find_result.first->first << ", " << find_result.first->second << std::endl;
            find_result.first++;
        }
    }
    return 0;
}
// 输出结果
// B, 1
// B, 5
  • 通过lower_bound(key)返回一个指向和参数相等大于参数的第一个元素的迭代器,或指向结束位置的迭代。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::multimap<std::string, int> multimap_values = {{"A", 10}, {"A", 15}};
    multimap_values.insert({{"B", 1}, {"C", 1}, {"A", 1}, {"B", 5}});

    auto find_result = multimap_values.lower_bound("B");
    while (find_result != multimap_values.end()) {
        std::cout << find_result->first << ", " << find_result->second << std::endl;
        find_result++;
    }
    
    return 0;
}
// 输出结果
// B, 1
// B, 5
// C, 1
  • 通过upper_bound(key)返回一个指向和参数大于参数的第一个元素的迭代器,或指向结束位置的迭代。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::multimap<std::string, int> multimap_values = {{"A", 10}, {"A", 15}};
    multimap_values.insert({{"B", 1}, {"C", 1}, {"A", 1}, {"B", 5}});

    auto find_result = multimap_values.upper_bound("B");
    while (find_result != multimap_values.end()) {
        std::cout << find_result->first << ", " << find_result->second << std::endl;
        find_result++;
    }
    
    return 0;
}
// 输出结果
// C, 1

删除元素

  • 通过erase(key)删除全部对应键的元素。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::multimap<std::string, int> multimap_values = {{"A", 10}, {"A", 15}};
    multimap_values.insert({{"B", 1}, {"C", 1}, {"A", 1}, {"B", 5}});

    size_t count = multimap_values.erase("A");
    std::cout << "remove count " << count << std::endl;

    auto find_result = multimap_values.begin();
    while (find_result != multimap_values.end()) {
        std::cout << find_result->first << ", " << find_result->second << std::endl;
        find_result++;
    }

    return 0;
}
// 输出结果
// remove count 3
// B, 1
// B, 5
// C, 1
  • 通过erase(iterator __position)或者erase(const_iterator __first, const_iterator __last)删除从指定迭代器范围的数据,返回一个指向最后一个被删除元素之后的迭代器。
#include <map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::multimap<std::string, int> multimap_values = {{"A", 10}, {"A", 15}};
    multimap_values.insert({{"B", 1}, {"C", 1}, {"A", 1}, {"B", 5}});

    find_result = multimap_values.erase(++multimap_values.begin());
    while (find_result != multimap_values.end()) {
        std::cout << find_result->first << ", " << find_result->second << std::endl;
        find_result++;
    }

    return 0;
}
// 输出结果
// C, 1

unordered_map

unordered_map与map一样都是唯一键值对的元素容器。但与map不同的是其中元素不是有序的,元素的位置由哈希值确定,因而必须有一个适用与键类型的哈希函数。

初始化

  • 使用初始化列表进行初始化,使用默认值初始化哈希表大小
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_map<std::string, int> u_map_values {
            {"A", 10},
            {"B", 20}
    };
    return 0;
}
  • 使用初始化列表进行初始化,使用指定值初始化哈希表大小
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"A", 10},
             {"B", 20},
             {"C", 30}}, 100 // 哈希表大小
    };
    return 0;
}

添加元素

  • 通过insert函数使用列表批量插入数据。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"A", 10},
             {"B", 20},
             {"C", 30}}, 100 // 哈希表大小
    };
    u_map_values.insert({{"D", 40},{"E", 50}});
    return 0;
}
  • 通过insert函数使用范围迭代器插入数据。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"A", 10},
             {"B", 20},
             {"C", 30}}, 100 // 哈希表大小
    };
    u_map_values.insert({{"D", 40},{"E", 50}});
    
    std::unordered_map<std::string, int> copy_map;
    copy_map.insert(u_map_values.begin(), u_map_values.end());
    
    return 0;
}
  • 通过emplace函数添加数据。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"A", 10},
             {"B", 20},
             {"C", 30}}, 100 // 哈希表大小
    };
    u_map_values.emplace("D", 40);
    return 0;
}

通过emplace_hint函数添加数据到指定位置。

#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"ZS", 10},
             {"LS", 20},
             {"WU", 30}}, 100 // 哈希表大小
    };
    u_map_values.emplace_hint(++u_map_values.begin(), "ZL", 40);
    return 0;
}

访问元素

  • 通过[key]来访问容器中的元素,如果没有找到对应元素则添加一个元素。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"ZS", 10},
             {"LS", 20},
             {"WU", 30}}, 100 // 哈希表大小
    };
    std::cout << u_map_values["LS"] << std::endl;
    return 0;
}
  • 通过at(key)来访问容器中的元素,如果没有找到对应的元素则抛出out_of_range异常。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"ZS", 10},
             {"LS", 20},
             {"WU", 30}}, 100 // 哈希表大小
    };
    std::cout << u_map_values.at("ZS") << std::endl;
    return 0;
}
  • 通过find(key)访问元素,该方法返回一个指向该元素的迭代器。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"ZS", 10},
             {"LS", 20},
             {"WU", 30}}, 100 // 哈希表大小
    };
    std::cout << u_map_values.find("ZS")->second << std::endl;
    return 0;
}

删除元素

  • 通过具体的键删除元素,删除成功返回1,否则返回0。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"ZS", 10},
             {"LS", 20},
             {"WU", 30}}, 100 // 哈希表大小
    };
    
    auto result = u_map_values.erase("ZS");
    return 0;
}
  • 通过具体位置的迭代器删除元素。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_map<std::string, int> u_map_values {
            {{"ZS", 10},
             {"LS", 20},
             {"WU", 30}}, 100 // 哈希表大小
    };
    
    auto result = u_map_values.find("ZS");
    if(result != u_map_values.end())
        u_map_values.erase(result);
    return 0;
}

自定义类型键

自定义类型的键需要类对象在实现hash()operator==两个函数。

class Name {
public:
    Name(const std::string _name) {
        name_ = _name;
    }
    /* 必要函数1:生成hash值函数 */
    size_t hash() const {
        size_t hash_code = std::hash<std::string>()(name_);
        std::cout << "name = " << name_ << ", hash code = " << hash_code << std::endl;
        return hash_code;
    }
    /* 必要函数2:恒等比较函数 */
    bool operator==(const Name & _name) const {
        return name_ == _name.name_;
    }
private:
    std::string             name_;
};

在提供一个类其中实现operator()来调用哈希校验。

class Hash_Name
{
public:
    size_t operator()(const Name & _name) const {
        return _name.hash();
    }
};

声明容器。

#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_map<Name, int, Hash_Name> u_map_values {{
        {{"A"},10},
        {{"B"},20}
    },2, Hash_Name()};
    auto result = u_map_values.insert({{"C"},10});
    std::cout << std::boolalpha << result.second << std::endl;
    return 0;
}

unordered_multimap

unordered_multimap是一个允许有重复键的无序map。

初始化

  • 使用初始化列表进行初始化,使用默认值初始化哈希表大小
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {"A", 10},
            {"B", 20}
    };
    return 0;
}
  • 使用初始化列表进行初始化,使用指定值初始化哈希表大小
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}};
    return 0;
}

添加元素

  • 通过insert函数使用列表批量插入数据。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
	std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };
    u_map_values.insert({{"BS", 40},{"BS", 50}});
    return 0;
}
  • 通过insert函数使用范围迭代器插入数据。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };
    u_map_values.insert({{"BS", 40},{"BS", 50}});
    
    std::unordered_multimap<std::string, int> copy_map;
    copy_map.insert(u_map_values.begin(), u_map_values.end());
    
    return 0;
}
  • 通过emplace函数添加数据。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };
    u_map_values.emplace("D", 40);
    return 0;
}

通过emplace_hint函数添加数据到指定位置。

#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };
    u_map_values.emplace_hint(++u_map_values.begin(), "ZL", 40);
    return 0;
}

访问元素

  • 通过equal_range[key]获取全部对应值的范围迭代器。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };

    auto result_it = u_map_values.equal_range("ZS");

    while (result_it.first != result_it.second) {
        std::cout << "key = " << result_it.first->first << ", value = " << result_it.first->second <<std::endl;
        ++result_it.first;
    }
    return 0;
}
  • 通过count(key)访问key所对应的值的数量。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };
	auto result = u_map_values.count("ZS");
    std::cout << result << std::endl;
    return 0;
}

删除元素

  • 通过具体的键删除全部对应元素,删除成功返回1,否则返回0。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };
    
    auto result = u_map_values.erase("ZS");
    return 0;
}
  • 通过具体位置的迭代器删除元素。
#include <unordered_map>
#include <iostream>
#include <string>

int main(int argc, char * argv[]) {
    std::unordered_multimap<std::string, int> u_map_values {
            {{"ZS", 10},
             {"ZS", 20},
             {"ZS", 30},
             {"BS", 10}}, 100 // 哈希表大小
    };

    auto result = u_map_values.equal_range("ZS");
    int count = u_map_values.count("ZS");
    for (int index = 0; index < count; ++index) {
        u_map_values.erase(result.first++);
    }

    std::cout << u_map_values.size() << std::endl;
    return 0;
}
上一篇:python 进程池实现 pool


下一篇:Java 四种线程池的用法分析