zoukankan      html  css  js  c++  java
  • 12、C++ Primer 4th 笔记,关联容器(2)

    1map set 容器中,一个键只能对应一个实例。multimapmultiset类型允许一个键对应多个实例。其支持的操作分别与mapset的操作相同,只有一个例外,multimap不支持下标运算。setmultiset专门用于存储键。

    2、关联容器 map set 的元素是按顺序存储的。而 multimap multset 也一样。因此,在 multimap multiset 容器中,如果某个键对应多个实例,则这些实例在容器中将相邻存放。迭代遍历 multimap multiset 容器时,可保证依次返回特定键所关联的所有元素。

    3、在multimapmultiset中寻找元素时,一般有以下三种方法:

    1)使用 find count count 函数求出某键出现的次数,而 find 操作则返回一个迭代器,指向第一个拥有正在查找的键的实例。

    2)用标准库提供的迭代器

    m.lower_bound(k)

    返回一个迭代器,指向键不小于 k 的第一个元素

    m.upper_bound(k)

    返回一个迭代器,指向键大于 k 的第一个元素

    m.equal_range(k)

    返回一个迭代器的 pair 对象它的 first 成员等价于m.lower_bound(k)。而 second 成员则等价于 m.upper_bound(k)

        若该键没有关联的元素,则 lower_bound upper_bound 返回相同的迭代

    器:都指向同一个元素或同时指向 multimap 的超出末端位置。它们都指向在保

    持容器元素顺序的前提下该键应被插入的位置。

    4、一个查找文本的例子

    #include "map"
    #include "set"
    #include "vector"
    #include "string"
    #include "fstream"
    #include "iostream"
    #include "sstream"
    using namespace std;
    
    class TextQuery
    {
    public:
    	typedef std::vector<std::string>::size_type line_no;
    	void read_file(std::ifstream &is) //读取文件,构造内部数据结构
    	{
    		store_file(is);
    		build_map();
    	}
    	std::set<line_no> run_query(const std::string&) const; //执行查找
    	std::string text_line(line_no) const; //返回找到单词的该行文本
    private:
    	void store_file(std::ifstream&); //存储文件
    	void build_map(); //将每个单词与相关联的行号建立映射
    	std::vector<std::string> lines_of_text; //存储原文件的每一行
    	std::map< std::string, std::set<line_no> > word_map; //映射结构
    };
    
    void TextQuery::store_file(std::ifstream &is)
    {
    	string textline;
    	while(getline(is, textline))
    	{
    		lines_of_text.push_back(textline);
    	}
    }
    
    void TextQuery::build_map()
    {
    	for(line_no line_num = 0; line_num != lines_of_text.size(); ++line_num)
    	{
    		istringstream line(lines_of_text[line_num]);
    		string word;
    		while (line >> word)
    		{
    			word_map[word].insert(line_num);
    			//word_map.insert(make_pair(word, line_num));
    			//word_map.insert(map<std::string, line_no>::value_type(word, line_no));
    		}
    	}
    }
    
    std::set<TextQuery::line_no>
    TextQuery::run_query(const string &query_word) const
    {
    	map<string, set<line_no> >::const_iterator loc = word_map.find(query_word);
    	if (loc == word_map.end())
    		return set<line_no>(); //not found, return empty set
    	else 
    		return loc->second;
    }
    
    std::string TextQuery::text_line(line_no line) const
    {
    	if (line < lines_of_text.size())
    		return lines_of_text[line];
    	else
    		throw std::out_of_range("line number out of range");
    }
    
    ifstream& open_file(ifstream &in, const string &file)
    {
    	in.close(); // close in case it was already open
    	in.clear(); // clear any existing errors
    	// if the open fails, the stream will be in an invalid state
    	in.open(file.c_str()); // open the file we were given
    	return in; // condition state is good if open succeeded
    }
    
    string make_plural(size_t ctr, const string &word,
    				   const string &ending)
    {
    	return (ctr == 1) ? word : word + ending;
    }
    
    void printf_resluts(const set<TextQuery::line_no> &locs, const std::string &sought, const TextQuery &file)
    {
    	typedef set<TextQuery::line_no> line_nums;
    	line_nums::size_type size = locs.size();
    	cout << "\n" << sought << "occurs "
    		 << size << make_plural(size, "time", "s")
    		 << endl;
    	line_nums::const_iterator it = locs.begin();
    	for (; it != locs.end(); it++)
    	{
    		cout << "\t(line"
    			 << (*it) + 1 << ")"
    			 << file.text_line(*it)
    			 << endl;
    	}
    }
    
    int main(int argc, char **argv)
    {
    	ifstream infile("C:\\1.txt");
    	/*if (argc < 2 || !open_file(infile, argv[1]))
    	{
    		cerr << "No input file" << endl;
    		return EXIT_FAILURE;
    	}*/
    	
    	TextQuery tq;
    	tq.read_file(infile);
    
    	while (true)
    	{
    		cout << "Enter word to look for, or q to quit: ";
    		string s;
    		cin >> s;
    		if (!cin || s == "q")
    			break;
    		set<TextQuery::line_no> locs = tq.run_query(s);
    		printf_resluts(locs, s, tq);
    	}
    	return 0;
    }
    

    注意上面例子中:

    word_map[word].insert(line_num);
    不能替换成如下两种形式
    //word_map.insert(make_pair(word, line_num));
    //word_map.insert(map<std::string, line_no>::value_type(word, line_no));
    

    因为make_pair的两个实参必须是具体的值,而不能是变量。

    参考:

    [1] http://blog.163.com/zhoumhan_0351/blog/static/399542272010227112325224/

    http://blog.163.com/zhoumhan_0351/blog/static/39954227201032392545410/

    http://blog.163.com/zhoumhan_0351/blog/static/399542272010229828061/

    http://blog.163.com/zhoumhan_0351/blog/static/39954227201038102838349/

    http://blog.163.com/zhoumhan_0351/blog/static/399542272010396030501/

    http://blog.163.com/zhoumhan_0351/blog/static/39954227201039112031737/

    http://blog.163.com/zhoumhan_0351/blog/static/39954227201022994439573/

  • 相关阅读:
    SVM
    决策树
    神经网络
    机器学习之降维方法
    机器学习之特征选择
    浏览器状态码大全
    哈希表
    社区发现算法总结(二)
    社区发现算法总结(一)
    聚类篇-------度量
  • 原文地址:https://www.cnblogs.com/mydomain/p/1989652.html
Copyright © 2011-2022 走看看