[C/C++标准库]_[初级]_[map的查找函数分析]

场景:

1. map在查找非数值索引(数值非重复索引可以使用vector)的对象时是高效率的,因为用的红黑树的实现,查找和插入都是logarithmic time 效率很高.

2.map可以说是很实用的数据结构.

3.使用multimap可以存储重复key,使用场景就是1对多的情况,比如一个联系人对应多个分组.

void TestMap()
{
	//map一般是通过红黑树来实现.http://en.cppreference.com/w/cpp/container/map
	//multimap也一样的
	//这里提示下map的优点是key是自动排序的,当然可以设置key的排序方式.在map的构造函数里.
	//1.判断map里是否包含某个key.可以使用count和find.
	//find是找到第一个之后可以直接使用,count只是统计个数.两个的时间其实是一样的,
	//硬要说的话是find找到第一个之后直接结束,对于map这种只有唯一key的速度是一样的,时间复杂度是 logarithmic time
	typedef map<int,int> TMap;
	typedef multimap<int,int> TTMap;
	TMap m;
	m[1] = 8;
	m[2] = 10;
	m[5] = 11;

	TTMap mm;
	mm.insert(pair<int,int>(1,8));
	mm.insert(pair<int,int>(2,10));
	mm.insert(pair<int,int>(1,11));
	mm.insert(pair<int,int>(1,12));

	//count
	int count = 0;
	if(count = m.count(1))
	{
		//1.如果要使用,还是得使用[]查找一次.
		//输出: m.count(1): 1
		cout << "m.count(1): " << count << endl;
	}

	if(count = mm.count(1))
	{
		//1.如果要使用,还是得使用equal_range查找一次.
		//multimap没有[]操作符重载,因为key不是唯一.
		//输出 mm.count(1): 3
		cout << "mm.count(1): " << count << endl;
	}

	//查看下count的实现,是使用equal_range来实现的.
	//equal_range是获取所有等于key的value组成一个连续的iterator,
	//其中pair第一个是匹配key的第一个iterator,第二个是大于key的第一个iterator.
	//map
	pair<TMap::iterator,TMap::iterator> values =  m.equal_range(1);
	TMap::iterator b = values.first;
	//输出 map equal_range: 8
	while(b != values.second)
	{
		cout << "map equal_range: " << (*b).second << endl;
		++b;
	}

	//multimap
	pair<TTMap::iterator,TTMap::iterator> valuess =  mm.equal_range(1);
	TTMap::iterator bs = valuess.first;

	//输出:
	//multimap equal_range: 8
	//multimap equal_range: 11
	//multimap equal_range: 12
	while(bs != valuess.second)
	{
		cout << "multimap equal_range: " << (*bs).second << endl;
		++bs;
	}

	//Find,找到匹配key的第一个iterator,不能找到第二个,如果需要找第二个,使用equal_range
	//Find 使用lower_bound来实现查找,lower_bound 查找大于或等于key的第一个元素.
	//与之类似的upper_bound来实现查找,它查找大于key的第一个元素.
	TMap::iterator ite = m.find(1);
	if(ite != m.end())
	{
		//1.直接使用iterator即可
		//输出: m.find 8
		cout << "m.find " << (*ite).second << endl;;
	}
	ite = m.lower_bound(3);
	if(ite != m.end())
	{
		//输出 m.lower_bound key 5 m.lower_bound 11
		cout << "m.lower_bound key " << (*ite).first << " m.lower_bound " << (*ite).second << endl;
	}
	//multimap
	bs = mm.lower_bound(1);
	if(ite != m.end())
	{
		//输出: mm.lower_bound key 1 mm.lower_bound 8
		cout << "mm.lower_bound key " << (*bs).first << " mm.lower_bound " << (*bs).second << endl;
	}
	bs = mm.upper_bound(1);
	if(ite != m.end())
	{
		//输出: mm.upper_bound key 2 mm.upper_bound 10
		cout << "mm.upper_bound key " << (*bs).first << " mm.upper_bound " << (*bs).second << endl;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	TestMap();

	return 0;
}
时间: 2024-12-09 06:52:40

[C/C++标准库]_[初级]_[map的查找函数分析]的相关文章

[C/C++标准库]_[初级]_[使用ctype里的isxxx函数时要注意的事项]

场景: 1. 标准库里的 ctype.h里的函数是用于1个字节的判断的,但是参数却是int, 这样很容易导致误用. isalpha iscntrl isdigit isgraph isprint ispunct isspace isxdigit isalnum islower isupper int isspace( int ch ); 最恶心的是vc++的实现会对超过1字节的值会直接崩溃,gcc不会!!! #if defined (_DEBUG) extern "C" int __c

[C/C++标准库]_[初级]_[交集和补集]

场景: 1. 计算std::vector A和 std::vector B里的相同的元素, 用于保留不删除. 2. 计算std::vector A和 std::vector B里各自的补集, 用于删除A的补集和添加B的补集,用在一些更新关联表的操作里. 比如联系人A所属分组B是一个集合BV, 把联系人A的所属分组 修改为集合CV, 就需要删除两个集合BV,CV的CV补集和新增BV补集. 3. C++标准库为我们提供了这些算法. 代码: // test_AndroidAssistant.cpp :

[C/C++标准库]_[初级]_[使用模板删除字符串前后空格((w)string space)]

场景: 1. C++没有提供删除std::(w)string的前后空格的函数,比如TrimSpace. 2. 很多库都提供, 但是为了移植代码方便,最好还是能用标准库解决就用标准库. 下边用模板实现了移除空格的函数. test.cpp #include <iostream> #include <stdlib.h> #include <string.h> #include <string> #include <ctype.h> using name

[C/C++不常见语法特性]_[初级]_[左值-右值-lvalue-rvalue]

参考:1. http://en.cppreference.com/w/cpp/language/value_category   << Value categories >> 2. https://msdn.microsoft.com/en-us/library/dd293668.aspx   << Rvalue Reference Declarator: && >>3. https://msdn.microsoft.com/en-us/li

[zlib]_[初级]_[使用Zlib完整解压zip内容]

场景: 1. 解压文件一般用在下载了一个zip文件之后解压,或者分析某个文件需要解压的操作上. 2. 解压文件,特别是解压带文件夹的zip文件往往系统没有提供这类Win32 API,当然C#自带库能解压, 当然这里只讨论C/C++, 像C#和Java这种开挂的标准库不在考虑范围内. 3. zlib解压文件的使用例子在 contrib\minizip 例子里. 这里基本是直接提取miniunz.c 的代码进行封装解压即可, 只是改了下支持中文路径. 主文件 zip_util.cpp #includ

C标准库-数值字符串转换与内存分配函数

原文链接:http://www.orlion.ga/977/ 一.数值字符串转换函数 #include <stdlib.h> int atoi(const char *nptr); double atof(const char *nptr); 返回值:转换结果 atoi把一个字符串开头可以识别成十进制整数的部分转换成int型,例如atoi("   -123abc")返回-123(字符串开头可以有空格).如果字符串开头没有可识别的整数返回0,而atoi("0abc&

[C/C++标准库]_[初级]_[std::vector的多线程读写问题]

场景: 1. 有时候需要使用vector 或 map作为多线程的共享变量, map是tree结构, 读和写方法都不是线程安全的, 即同时读写会有崩溃的现象. 2. std::vector直观来说只用push_back和[] 下标访问操作应该没问题,push_back往后边加对象, 索引值只访问已经存储的变量(预先求size).注意, 这里不会删除vector元素. 可惜,这种多线程操作还是会崩溃. 单线程写和单线程读!!! 看代码: test_vector.cpp #include "gtest

[C/C++标准库]_[初级]_[使用fstream合并文本文件]

场景: 1. 就是合并文本文件,并且从第2个文件起不要合并第一行. 2. 多加了一个功能,就是支持2个以上的文件合并. 3. 问题: http://ask.csdn.net/questions/192151 只能说很简单: 基础不过关吧,这位同学,也有可能不是开发的,放这里也是为了培训基础差的. test.cpp #include <fstream> #include <string> #include <iostream> using namespace std; /

[C/C++标准库]_[初级]_[过滤Windows文件名中的非法字符]

场景: 1. 通常生成文件时需要一个文件名,而生成文件名的方式可能是通过用户输入的字符,但是有些字符在windows上是不能作为文件名的,强行创建这类文件会失败. 2.一般可以通过正则表达式替换所有的非法字符,这里实现的是C++98 template(模板)方式的替换无效字符,std::string,std::wstring. 基本上windows上和字符串打交道都离不开wstring. 函数: template<class T> void FilterInvalidFileNameChar(