1.set的宣言
先看看C++标准中对set的介绍:
A set is a kind of associative container that supports unique keys (contains at most oneof each key value) and provides for fast retrieval of the keys themselves. Set supportsbidirectional iterators
下面列举关于set的两点事实,需要注意:
- set对于性能有明确的保证:set::find和set::insert消耗时间级别都为logN。所以,如果你确实需要保证插入和检索时间在logN,set可能是个不错的选择。
- set底层实现通常使用red-black tree:有额外的空间和时间负担。每个red-black tree的节点都需要存储颜色标记、指向子女和父亲的指针;插入需要树的重新平衡;查询和遍历需要指针操作。
2.另外的选择:二分查找
红黑树并非提供logN级别的搜索的唯一数据结构。很容易想到的就是在有序数集中进行binary_search,该算也提供的logN级别的时间复杂度,而且最数据结构的要求仅仅是“一个有序顺序集(该集支持某些必要操作)”,而且, 常数因子比set更小。使用set会占用更多的空间,不利于cache机制的使用,且可能造成更多的page faults。
事实胜于雄辩,下面是用一段代码来对比set提供的搜索和二分查找提供的搜索的性能,编译环境为WOW64 Release
注意: 检测元素是否搜索到是必须的,此处忽略之,对于push_back等的调用其实可以使用“范围函数”来完成,可能性能更好!
#include <iostream>#include <set>#include <vector>#include <algorithm>#include <windows.h>int main()
{using namespace std;const int MAX_ELEMENT = 1000000;const int MAX_SIZE = MAX_ELEMENT+1;const int MAX_TIMES = 10000000;set<int> intSet;
vector<int> intVect;
intVect.reserve(MAX_SIZE);for (int i = 0; i < MAX_SIZE; ++i)