1.set的宣言

先看看C++标准中对set的介绍:

A set is a kind of associative container that supports unique keys (contains at most one
of each key value) and provides for fast retrieval of the keys themselves. Set supports 
bidirectional iterators

下面列举关于set的两点事实,需要注意:

  1. set对于性能有明确的保证:set::find和set::insert消耗时间级别都为logN。所以,如果你确实需要保证插入和检索时间在logN,set可能是个不错的选择。
  2. 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)