【C++】map 和 set

         Map和set是两种最典型的关联式容器,使用平衡树(通常为红黑树)作为其底层的数据结构,可以做到有序地管理数据,与数据查找相关的操作,效率明显优于常见的序列式容器,例如vector、list等。

        本篇博客梳理了map和set的特性和常见用法,并搭配对STL源码的解析和模拟实现,将上层用法与底层实现相结合,旨在更好地向读者呈现C++中面向对象和泛型编程的思想,以及更进一步地理解STL的组件之一仿函数。

目录

一、序列式容器与关联式容器

二、树形结构的关联式容器

1. map

2. set

三、同一种底层数据结构支持两种不同的容器

1. STL源码解析

2. 模拟实现

2-1.上下互通

2-2.数据比较

2-3.迭代器

2-3-1.普通.vs.const

2-3-2.前置++ 

2-3-3.前置--

2-3-4.map的[ ]重载

2-3-5. [ ]重载的遗留问题

3.模拟实现的完整代码

· RBTree.h

· Map.h

· Set.h

补、multimap

补、multiset

补、一些精华笔试题

附、 rbtree、map、set源码

· rbtree

· map

· set


一、序列式容器与关联式容器

        从存储数据的方式和内容而言,STL容器有序列式容器和关联式容器之分。

        序列式容器仅存储数据元素本身其底层通常为数组或链表,例如vector、list、stack、list、deque、priority_queue等。

        而关联式容器存储的是有序的键值对(一个键值和一个实值),其底层通常为平衡树或哈希表,例如map、set、unordered_map、unordered_set等。

        两类容器的最大区别在于容器内部元素的顺序。此外,因其特性、适配的场景和需求,两类容器插入、删除和查找等操作的时间复杂度也有所不同。

【补】键值对

        键值对是用来表示映射关系的一种结构,该结构中一般只包含两个成员变量key和value,其中,key代表键值value表示与key键值一一对应的实值

        在日常生活中,键值对最有代表性的应用就是一本能够英汉互译的词典。在英汉互译的词典中,每一个英文单词都有它自己的中文含义,且每一个英文单词与之中文含义,都是一一对应的关系。如此,想要在词典中得知某一个单词的中文含义,只需在词典中直接查询这个单词的英文本体即可。

//VS2019的SGI-STL中,是这样定义键值对的:
template <class T1, class T2>
struct pair 
{
    typedef T1 first_type;
    typedef T2 second_type;
    T1 first;                //key
    T2 second;               //value
    pair(): first(T1()), second(T2())
    {}
    pair(const T1& a, const T2& b): first(a), second(b)
    {}
};
//其中T1类型的first变量代表key,T2类型的second变量代表value
//key和value的实际类型可由使用者指定,体现了泛型的思想

二、树形结构的关联式容器

1. map

        Map(映象)是一种以<key,value>键值对作为数据元素的关联式容器,底层为平衡树,可以按照特定的键值key的次序存储数据元素,使用时需包含该容器的头文件“#include<map>”。在一个键值对中,键值key的功能是排序数据元素和标识数据元素(map中的元素总是按照键值key进行比较排序的),实值value的功能是存储与键值key对应的实值信息键值key和实值value的类型可以不同,且在map的内部,两者是通过成员类型value_type绑定在一起的。

        对map中的所有元素进行迭代访问,可以得到一个有序的序列。且map支持下标访问符[],在[]中放入key,就可以找到与key对应的value。

        在map定义的模板参数中,key表示键值对中key的类型,T表示键值对中value的类型,

Compare表示比较器(map中的元素是严格按照key来比较排序的,Compare参数缺省的情况下默认按照小于比较/升序。比较内置类型的元素时无需要传递该参数,比较自定义类型的元素则需要自行显式传参函数指针或者仿函数),Alloc表示空间配置器(该参数用于申请底层空间来动态处理其存储需求,除非不想使用标准库提供的空间配置器,一般无需传递)。

        map的特性如下:

  1. 关联性。map中的元素在容器中如何存放与它们的键值key有关,与它们在容器中的绝对位置无关。
  2. 有序性。容器中的元素始终遵循严格的顺序,所有插入的元素都按此顺序拥有一个既定位置。
  3. 唯一性。map中每个元素的键值key是唯一的,没有任意两个元素拥有相等的键值key。
  4. 映射关系。每个元素都是一个key和value的键值对,其中的键值key与实值value一一对应。
  5. 分配器智能化。map借助分配器可以动态处理其存储需求。

        map的常见用法如下:

//class A
//{
//public:
//    A(int a1, int a2)
//        :_a1(a1)
//        , _a2(a2)
//    {}
//private:
//    int _a1;
//    int _a2;
//};
void test_map1()
{
    map<string, string> dict;
    pair<string, string> kv1("insert","插入");
    //插入
    dict.insert(kv1);                                  //一般方式
    dict.insert(pair<string, string>("sort", "排序")); //匿名方式
    dict.insert(make_pair("string", "字符串"));        //C++98方式
    dict.insert({ "string", "字符串" });               //C++11方式 多参数的构造函数隐式类型转换

    
    //[补]c++98单参数的类型支持隐式类型转换
    //string str1 = "hello";
    //A aa1 = { 1,2 };
    //pair<string, string> kv2 = { "string","字符串" };   
}
void test_map2()
{
    map<string, string> dict;
    dict.insert(make_pair("string", "字符串"));
    dict.insert(make_pair("sort", "排序"));
    dict.insert(make_pair("insert", "插入"));

    dict.insert(make_pair("insert", "xxxx"));// 此语句不插入且不覆盖
    // 插入过程中,只比较key,value相同与否无所谓
    // 若key已经有了就不插入了
    
    //迭代器遍历
    //map<string, string>::iterator it = dict.begin();
    auto it = dict.begin();
    while (it != dict.end())
    {
        //pair本身是不支持流插入/流提取,因为库中没有实现
        //要打印pair需指明左值、右值
        //以下两种写法均可:
        cout << (*it).first << ":" << (*it).second << endl;//此处it解引用后是pair*
        cout << it->first << ":" << it->second << endl;
        //理应为it->->first,但编译器会优化为it->first。第一个 “->” 是一个重载,返回pair的指针(pair*)
        //注意:
        //it->first = "xxx";//左值无法修改
        //it->second = "xxx";//但右值可以修改
        
        ++it;
    }
    cout << endl;

    for (const auto& kv : dict)//范围for需加&,不修改加const
    {
        cout << kv.first << ":" << kv.second << endl;
    }
}
void test_map3()
{
    //情景:要统计每种水果出现的次数

    string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
    map<string, int> countMap;
    
    //写法一
    //for (auto e : arr)
    //{
    //	auto it = countMap.find(e);
    //	if (it == countMap.end())
    //	{
    //		countMap.insert(make_pair(e, 1));
    //	}
    //	else
    //	{
    //		it->second++;
    //	}
    //}

    //写法二
    for (auto e : arr)
    {
        countMap[e]++; 
        // [] 重载,可以通过key返回value
        //1.若key已在平衡树中,则返回pair<树中key的所在节点的iterator,false>
        //2.若key不在平衡树中,则返回pair<新插入key的所在节点的iterator,true>
        //除了有插入功能,还有查找功能
    }

    for (const auto& kv : countMap)
    {
        cout << kv.first << ":" << kv.second << endl;
    }
}
void test_map4()
{
    map<string, string> dict;
    dict.insert(make_pair("string", "字符串"));
    dict.insert(make_pair("sort", "排序"));
    dict.insert(make_pair("insert", "插入"));

    cout << dict["sort"] << endl;  // 查找和读取"sort"对应的"排序"
    dict["map"];                   // 插入新的key"map",但"map"没有对应的实值
    dict["map"] = "映射,地图";      // 修改"map"对应的实值
    dict["insert"] = "xxx";        // 修改"insert"对应的实值
    dict["set"] = "集合";          // 插入+修改
}

2. set

         Set(集合)也是一种关联式容器,底层为平衡树,可以对数据实现排序和去重,使用时需包含该容器的头文件“#include<set>”

        与map不同的是,set存储的数据元素不是key和value的键值对,而仅仅是实值value(但在底层实际存放的是由<value,value>构成的键值对)。每个实值value必须是唯一的,且在容器中不能被修改,只能从容器中插入或删除

        set仅支持迭代器访问,不支持下标访问符[]。对set中的所有元素依次进行迭代访问,可以得到一个有序的序列

        在set定义的模板参数中,T表示set中存放元素的类型(实际在底层存储的是键值对),

Compare表示比较器(与map类似,默认按照小于来比较/升序。比较内置类型的元素时无需要传递该参数,比较自定义类型的元素则需要自行显式传参函数指针或者仿函数),Alloc表示空间配置器(与map类似,用于申请底层空间来动态处理其存储需求,除非不想使用标准库提供的空间配置器,一般无需传递)。

        set的特性如下:

  1. 关联性。set中的元素在容器中如何存放与它们本身的实值value有关,与它们在容器中的绝对位置无关。
  2. 有序性。set元素始终遵循严格的顺序。所有插入的元素都按此顺序给定一个位置。
  3. 唯一性。set中每一个元素的实值value是唯一的,没有任意两个元素的实值value是相同的。
  4. 可排序且可去重。由set容器中元素的特点以及set的有序性、唯一性,set具有排序+去重的功能。
  5. 分配器智能化。set借助分配器可以动态处理其存储需求。

        set的常见用法如下:

void test_set1()
{ 
    set<int> s;
    //插入一个实值value
    s.insert(3);
    s.insert(2);
    s.insert(4);
    s.insert(5);
    s.insert(1);
    s.insert(5);
    s.insert(2);
    s.insert(5);
    
    //迭代器遍历
    set<int>::iterator it = s.begin();
    while (it != s.end())
    {
        cout << *it << " "; // 1 2 3 4 5 (排序+去重)
                            // 去重原理:一个值已经有了,就不插入
        ++it;
    }
    cout << endl;
    
    //范围for遍历,无需加引用
    for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;

    //在容器中删除一个实值value
    //方法1:找到它的位置再删除
    auto pos = s.find(3);  // O(logN)
    //auto pos = find(s.begin(), s.end(), 3); // O(N)
    //这里两个find()的重载函数,时间复杂度不同
    if (pos != s.end())
        s.erase(pos);
    //方法2:直接删除
    s.erase(30);

    for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;

    //在容器中查找一个实值
    if (s.find(5) != s.end())
    {
        cout << "找到了" << endl;
    }

    //计数容器中的一个实值
    if (s.count(5))
    {
        cout << "找到了" << endl;
    }


}
void test_set2()
{ 
    std::set<int> myset;
    std::set<int>::iterator itlow, itup;

    for (int i = 1; i < 10; i++)
        myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90
    myset.insert(35);//10 20 30 35 40 50 60 70 80 90

    // 标记实值的区间[30,60)
    //itlow = myset.lower_bound(30);                // >=     
    //itup = myset.upper_bound(60);                 // >


    //std::pair<std::set<int>::const_iterator, std::set<int>::const_iterator> ret;
    auto ret = myset.equal_range(30);//获取相等元素的范围,返回一个范围的边界(pair)
    itlow = ret.first;//返回的左值是相等元素范围的起始位置
    itup = ret.second;//返回的右值是相等元素范围结尾的下一个值的位置

    // [itlow, itup)
    cout << *itlow << endl; //30
    cout << *itup << endl;  //35

    myset.erase(itlow, itup);//删除区间[30,35)中的实值                    

    for (auto e : myset)
    {
        cout << e << " "; //10 20 35 40 50 60 70 80 90
    }
    cout << endl;
}

三、同一种底层数据结构支持两种不同的容器

1. STL源码解析

        map和set的底层数据结构都是红黑树,更准确的说,在STL库中,它们的底层其实是同一种红黑树。

        Set的第一个模板参数、map的第二个模板参数和红黑树的第二个模板参数,它们之间的交互使红黑树能够实现“同一种底层数据结构支持两种不同的容器”,体现了泛型的思想。

        但紧接着又会生成一个新的疑问,既然红黑树的第二个模板参数如此关键,那它的第一个模板参数就可以忽略了吗?它又有什么样的作用呢?

        其实map和set仅仅是一层浅浅的封装,主要的核心实现都在底层的红黑树里面。

        以set来举例,如下图:

        set的大量功能实际上是由红黑树中支持的,红黑树中的许多接口在set中进行了一层封装。

        而对于在红黑树中实现的部分接口,例如find(),其中参数的类型是key_type,即红黑树的第一个模板参数key。对于set而言,红黑树中的第一个模板参数和第二个模板参数其实都是key;但对于map而言,红黑树的第一个模板参数是key,第二个模板参数是pair<key,value>。假若不传第一个模板参数,而试图用第二个模板参数去调用这些接口,那么这些接口就可能无法接收到适配的参数进而被调用,也就无法同时适配两个容器了。

        也就是说,set的类型实际被定义为<key,key>并不是空穴来风,而是为了在参数上与map和底层的红黑树做到统一地适配,从而使红黑树真正实现“同一种底层数据结构支持两种不同的容器”。

        但需注意,map和set严格来说使用的不是同一棵红黑树,而是同一个红黑树类的类模板。这是因为两个容器向同一个类模板所传的参数不同,在编译阶段会实例化出两个不同的类。

2. 模拟实现

2-1.上下互通

        以上对源码的解析中,红黑树、map、set三者的模板参数之间有统一适配的关系。由此,不难得到以下定义它们结构的基础代码:

//初步对红黑树的定义
enum Colour
{
	RED,
	BLACK
};

template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;

	T _data;
	Colour _col;

	RBTreeNode(const T& data)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _data(data)
		, _col(RED)
	{}
};
template<class K, class T>
struct RBTree
{
	typedef RBTreeNode<T> Node;
private:
	Node* _root = nullptr;
}

(关于红黑树的更多详解,请见【数据结构】平衡树之红黑树

    //初步对map的定义
	template<class K, class V>
	class map
	{
	private:
		RBTree<K, const pair<K, V>> _t; //map中的成员变量是一棵红黑树(根节点)
	};
    //初步对set的定义
	template<class K>
	class set
	{
	private:
		RBTree<K, K> _t; //set中的成员变量是一棵红黑树(根节点)
	};

【Tips】底层红黑树与上层两容器互通的基础,是三者之间的模板参数实现了统一的适配

2-2.数据比较

        红黑树的基本功能有查找、插入等。

         一棵红黑树基本是通过插入操作来构建的。插入操作大致可以分为两步:1.插入新数据;2.控制树平衡。在“1.插入新数据”中,先要按红黑树身为平衡搜索树的性质(比根小放根左边,比根大放根右边)来找到新数据适当的插入位置,这就涉及了数据的比较。

        对于set而言,它所存的值是key,仅需按照所存值key来比较即可。但对于map而言,它所存的值是<key,value>,需按照<key,value>中的key来比较。两者的数据类型是不同的,且它们分别将key和<key,value>传给红黑树的模板类型T以区分两者。

        在“寻找新数据适当的插入位置”之际,若直接比较数据本身,红黑树就仅能支持set,而不能支持map。

enum Colour
{
    //...
};

template<class T>
struct RBTreeNode
{
    //...
	T _data;
    //...
};

template<class K, class T>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
    //插入
	bool Insert(const T& data)
	{
        //step1.插入新数据:
        //利用插入的值创建一个新的树节点。
        //树为空,就直接将新节点赋给根节点的指针;
        //树不为空,就按二叉搜索树的性质查找到合适的插入位置,在合适位置插入新节点。
  		
        //树为空
        if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return true;
		}
        
        //树不为空

        //利用新数据创建新节点
        cur = new Node(data);
		cur->_col = RED;


        //寻找新数据适当的插入位置
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->data < data)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->data > data)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
        //此处是直接比较节点的数据本身的。
        //但因为set中所存是key,map中所存是<key,value>,
        //“直接比较数据本身”仅能满足set的比较需求,而不能满足map的比较需求
        //故这样的写法无法使红黑树同时支持两种不同的容器


        //找到适当位置后插入
		if (parent->data < data)
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
        //此处也是直接比较节点的数据本身。
 
		cur->_parent = parent;
 
        

        //step2.控制树的平衡:
        //调整颜色+旋转

        //...

	}
private:
	Node* _root = nullptr;
}

          那该如何优化,使存key的set直接按key来比较,也使存<key,value>的map按<key,value>中的key来比较呢?

        源码中给出的方案是,仿函数。即在红黑树、map、set三者的模板类型中,分别增加一个仿函数,使map和set可以通过各自的仿函数来将所实例化的对象中特定的数据取出。

    //map
    template<class K, class V>
	class map
	{
        //通过一个内部类来封装仿函数
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first; //map所传仿函数,返回<key,value>中的key
			}
		};

	public:
		bool insert(const pair<K, V>& kv)    //在底层红黑树的插入接口上套一层壳
		{
			return _t.Insert(kv);
		}

	private:
		RBTree<K, pair<K, V>, MapKeyOfT> _t;
	};
    //set
    template<class K>
	class set
	{
        //通过一个内部类来封装仿函数
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key; //set所传仿函数,直接返回key
			}
		};

     public:
		bool insert(const K& key)    //在底层红黑树的插入接口上套一层壳
		{
			return _t.Insert(key);
		}

	private:
		RBTree<K, K, SetKeyOfT> _t;
	};
//红黑树
enum Colour
{
    //...
};

template<class T>
struct RBTreeNode
{
    //...
	T _data;
    //...
};


// set->RBTree<K, K, SetKeyOfT> _t;
// map->RBTree<K, pair<K, V>, MapKeyOfT> _t;

template<class K, class T, class KeyOfT>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
    //插入
    bool Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return true;
		}

		Node* parent = nullptr;
		Node* cur = _root;

		KeyOfT kot;//仿函数提取特定的数据
		while (cur)
		{
			if (kot(cur->_data) < kot(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_data) > kot(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}

		cur = new Node(data);
		cur->_col = RED;

		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}

		//...

		return true;
	}

private:
	Node* _root = nullptr;
};

        这样一来,map和set就可以通过同一个底层的红黑树来进行数据的比较了。 

【Tips】仿函数是“两个不同容器的底层数据结构都是红黑树 ”的重要一环。

2-3.迭代器

2-3-1.普通.vs.const

        源码中,map和set迭代器的实现是在底层红黑树提供的迭代器上进行了一层封装。

        Set所存仅为key,排序也涉及key,所以它的普通迭代器和const迭代器均封装的是红黑树的const迭代器。这意味着set的迭代器只读不改

        这是因为, set的有序序列,是通过它的迭代器中序遍历红黑树而得到的。若它的迭代器可读可改,则得到的序列可能不是有序的,同时也可能破坏底层红黑树的搜索树性质。

        而map所存为<key,value>,排序仅涉及key而不涉及value,key不可改但value可改,所以map同时封装了红黑树的普通迭代器和const迭代器。这意味着map的迭代器可读可改

        红黑树中的迭代器实际上是一个自定义类型,封装了树节点的指针和解引用、自增自减等方法

//红黑树中迭代器的初步设计:
template<class T,class Ptr,class Ref>
struct __TreeIterator
{
	typedef RBTreeNode<T> Node;	
	typedef __TreeIterator<T,Ptr,Ref> Self;

	Node* _node;

	__TreeIterator(Node* node)
		:_node(node)
	{}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &_node->_data;
	}

	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}

//树节点
enum Colour
{
	RED,
	BLACK
};
template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	
	T _data;
	Colour _col;

	RBTreeNode(const T& data)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_data(data)
		,_col(RED)
	{}
};
//红黑树
template<class K, class T, class KeyOfT>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
	//以下两者属于同一个类模板,但因所传不同参数,实例化为不同类型
	typedef __TreeIterator<T, T*, T&> iterator; //可读可改的普通迭代器
	typedef __TreeIterator<T, const T*, const T&> const_iterator; //只读不改的const迭代器

	iterator begin()
	{
		Node* leftMin = _root; //这样写,是以防树是空树           
		while (leftMin && leftMin->_left) //有序序列中打头的数据应该是红黑树中的最左节点
		{
			leftMin = leftMin->_left; //因为上层容器是按中序遍历红黑树来得到有序序列的
		}

		return iterator(leftMin);
	}

	iterator end() //若it处于容器数据的末尾(树的最右节点),则++会使it中序遍历至根的父亲(而根的父亲为空),故end()返回空
	{
		return iterator(nullptr);
	}

	const_iterator begin() const
	{
		Node* leftMin = _root;
		while (leftMin && leftMin->_left)
		{
			leftMin = leftMin->_left;
		}

		return const_iterator(leftMin);
	}

	const_iterator end() const
	{
		return const_iterator(nullptr);
	}
    
    //...

private:
	Node* _root = nullptr;
};
//set的上层封装
    template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
        //set的普通迭代器和const迭代器均封装的是红黑树的const迭代器
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
        //注:
        //RBTree<K, pair<K, V>, SetKeyOfT>是一个类域,也是一个类模板,在被实例化前,并没有具体的代码。
        //因此,编译器可能认不出RBTree<K, pair<K, V>,SetKeyOfT>::iterator是一个类型,
        //也可能分不清iterator是类域中的内嵌类型(tydef或内部类)还是静态成员变量,
        //导致各种语法报错。
        //所以,在这里加入typename,目的是提示编译器
        //RBTree<K, pair<K, V>, SetKeyOfT>::iterator是一个类型
        //让编译器在类模板实例化之后再去类域中找到该类型  

		iterator begin() const //const修饰_t,强调_t是const对象,使普通对象也可以去调用树的const_iterator,下同
		{
			return _t.begin();
		}

		iterator end() const
		{
			return _t.end();
		}

		const_iterator begin() const
		{
			return _t.begin();
		}

		const_iterator end() const
		{
			return _t.end();
		}
        //实际上,此处仅需提供const_iterator版本的begin()和end()即可

		//...

	private:
		RBTree<K, K, SetKeyOfT> _t;
	};
//map的上层封装
    template<class K, class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:
        //map同时封装了红黑树的普通迭代器和const迭代器
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator; //const修饰k但不修饰value,使key可改但value不可改      
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;
		
		iterator begin()
		{
			return _t.begin();
		}

		iterator end()
		{
			return _t.end();
		}

		const_iterator begin() const //const修饰_t,强调_t是const对象,使begin()去调用树的const_iterator而非iterator,下同
		{
			return _t.begin();
		}

		const_iterator end() const
		{
			return _t.end();
		}

		//...

	private:
		RBTree<K, pair<K, V>, MapKeyOfT> _t;
	};

2-3-2.前置++ 

        容器的迭代器最大的作用就是遍历容器中的数据。红黑树作为一棵二叉平衡搜索树,可以通过中序遍历来得到一个有序序列。对于map、set这样以红黑树作为底层的有序容器,它们迭代器的前/后置++操作、前/后置--操作,是通过中序遍历红黑树来得到一个有序的数据序列的。

         根据中序的规则,迭代器(假设为it)是通过“左子树-根-右子树”的方式来遍历数据的,也就是说它整体在朝着树的右侧方向前进。

        当 it 处在上图位置,要找到中序的下一个节点“10”,只需找到其右子树的最左节点即可(因为这个最左节点一定是右子树中最小的节点)。

        当 it 处于上图位置,没有右孩子。要找到中序的下一个节点“6”,就应该找到 it 的父亲节点。

        当 it 处于上图位置,没有右孩子,且它的父亲节点也已经遍历过。要找到中序的下一个节点“8”,就应该向上去找到 it 的祖父节点当中,父亲为其左孩子的祖父节点(遍历到的当前节点是其父亲的右孩子,说明父亲已经遍历过,下一个应找祖父;而父亲在祖父的右边,说明祖父也已经遍历过,下一个应找曾祖父;只有祖父在曾祖父的左边,才说明曾祖父没有被遍历过,下一个就是曾祖父,否则还要去找曾曾祖父)。

【Tips】迭代器的前置++

  1. 若当前 it 的右不为空,则下一个访问的是,it 右子树的最左节点。
  2. 若当前 it 的右为空,则下一个访问的是,其左孩子也是 it 祖先或 it 自己的祖先节点。
//迭代器前置++
template<class T>
struct __TreeIterator
{
	typedef RBTreeNode<T> Node;
    typedef __TreeIterator<T> Self;
	Node* _node;

	__TreeIterator(Node* node)
		:_node(node)
	{}

    //...

    Self& operator++()
	{   
        //it的右不为空
		if (_node->_right)
		{
			//下一个访问的就是右子树的最左节点
			Node* subLeft = _node->_right; //标记右子树
			while (subLeft->_left) //找最左节点
			{
				subLeft = subLeft->_left;
			}

			_node = subLeft; //找到后标记
		}
        //it的右为空
		else
		{
            //下一个访问的就是,其左孩子也是it祖先或it自己的祖先节点。
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent) //找其左孩子也是it祖先的祖先节点
			{
				if (cur == parent->_left) //找到了就不继续找了
				{
					break;
				}
				else //没找到就继续往上找
				{
					cur = cur->_parent;
					parent = parent->_parent;
				}
			}

			_node = parent; //找到后标记
		}

		return *this; //返回已经指向中序的下一个节点的this指针
	}
};
2-3-3.前置--

         前置--相当于迭代器(假设为it)是通过反向的中序来遍历数据,即“右子树-根-左子树”,而它整体在朝着树的左侧方向前进。

        当 it 处在上图位置,要找到反向中序的下一个节点“11”,只需找到其左子树的最右节点即可(因为这个最右节点一定是左子树中最小的节点)。

        当 it 处于上图位置,没有左孩子。要找到反向中序的下一个节点“8”,就应该找到 it 的父亲节点。

        当 it 处于上图位置,没有左孩子,且它的父亲节点也已经遍历过。要找到中序的下一个节点“17”,就应该向上去找到 it 的祖父节点当中,其左孩子也是 it 祖先的祖先节点。

【Tips】迭代器的前置--

  1. 若当前 it 的左不为空,则下一个访问的是,it 左子树的最右节点。
  2. 若当前 it 的左为空,则下一个访问的是,其右孩子也是 it 祖先或 it 自己的祖先节点。
    Self& operator--()
	{
        // it 的左不为空
		if (_node->_left)
		{
			Node* subRight = _node->_left;
			while (subRight->_right)
			{
				subRight = subRight->_right;
			}

			_node = subRight; //找到 it 左子树的最右节点
		}
        // it 的左为空
		else
		{
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}

			_node = parent; //找到其右孩子也是 it 祖先或 it 自己的祖先节点
		}

		return *this;
	}

 

2-3-4.map的[ ]重载

        在源码中,map的[ ]重载是基于insert()实现的,而insert()又是对一层对红黑树提供的插入方法的封装。

          源码中将插入方法的返回值设为一个<迭代器,布尔值>的键值对,返回的是插入数据(节点)的迭代器和插入成功的真值/假值。

//红黑树提供的插入方法
template<class T>
struct RBTreeNode
{
    //...
};
template<class T, class Ptr, class Ref>
struct __TreeIterator
{
    //...
};
template<class K, class T, class KeyOfT>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
	typedef __TreeIterator<T, T*, T&> iterator;
	typedef __TreeIterator<T, const T*, const T&> const_iterator;

    //插入
    pair<iterator, bool> Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true); //返回<插入数据(节点)的迭代器,布尔值>
		}

		Node* parent = nullptr;
		Node* cur = _root;

		KeyOfT kot;
		while (cur)
		{
			if (kot(cur->_data) < kot(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_data) > kot(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}

		cur = new Node(data);
		cur->_col = RED;

		Node* newnode = cur; //将创建的新节点额外保存一份,以便后续作为返回值pair<iterator, bool> 中的iterator返回

		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}

		cur->_parent = parent;

		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else 
				{
					if (cur == parent->_left)
					{
						//     g
						//   p
						// c
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						RotateL(parent);
						RotateR(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}

					break;
				}
			}
			else // parent == grandfather->_right
			{
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						grandfather->_col = RED;
						parent->_col = BLACK;
					}
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}

					break;
				}
			}
		}

		_root->_col = BLACK;

		return make_pair(iterator(newnode), true); //返回<插入数据(节点)的迭代器,布尔值>
	}

    //左旋转
	void RotateL(Node* parent)
	{
		Node* cur = parent->_right;
		Node* curleft = cur->_left;

		parent->_right = curleft;
		if (curleft)
		{
			curleft->_parent = parent;
		}

		cur->_left = parent;

		Node* ppnode = parent->_parent;

		parent->_parent = cur;


		if (parent == _root)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;

			}

			cur->_parent = ppnode;
		}
	}

    //右旋转
	void RotateR(Node* parent)
	{
		Node* cur = parent->_left;
		Node* curright = cur->_right;

		parent->_left = curright;
		if (curright)
			curright->_parent = parent;

		Node* ppnode = parent->_parent;
		cur->_right = parent;
		parent->_parent = cur;

		if (ppnode == nullptr)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;
			}

			cur->_parent = ppnode;
		}
	}
//map在上层进一步封装
    template<class K, class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;

        //...

        //map的插入
		pair<iterator, bool> insert(const pair<K, V>& kv)
		{
			return _t.Insert(kv);
		}

        //map的[]重载
		V& operator[](const K& key) //接收key,返回value
		{
			pair<iterator, bool> ret = insert(make_pair(key, V())); //给insert()传的是<key,value的缺省>
			return ret.first->second;
		}

	private:
		RBTree<K, pair<const K, V>, MapKeyOfT> _t;
	};

 

2-3-5. [ ]重载的遗留问题

        为了支持map的[ ]重载,底层红黑树提供的插入方法,返回值为pair<iterator, bool> 。为了使红黑树继续能支持两种不同的容器,set中封装的insert()的返回值也应与pair<iterator, bool> 保持一致。

    //set
    template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key; 
			}
		};
     public:
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;

		pair<iterator, bool> insert(const K& key)
		{
			return _t.Insert(key);
		}

	private:
		RBTree<K, K, SetKeyOfT> _t;
	};

        但这会引发一个编译报错。

        这是因为set中所谓的迭代器iterator,实际上是封装的红黑树的const迭代器const_iterator,导致在set封装的insert()的返回值类型pair<普通迭代器, 布尔值>,实际上是pair<const迭代器, 布尔值>。而红黑树提供的插入方法,返回值的类型是<普通迭代器,布尔值>,与set的insert()返回值类型要求不符。

        而在源码中,这个问题是这样被巧妙解决的:

//红黑树
template<class T,class Ptr,class Ref>
struct __TreeIterator
{
	typedef RBTreeNode<T> Node;	
	typedef __TreeIterator<T,Ptr,Ref> Self;
	typedef __TreeIterator<T, T*, T&> Iterator;
    //对于普通迭代器对象,Self和Iterator含义相同,都是普通迭代器类型
    //但对于const迭代器对象,Self是const迭代器类型,Iterator是普通迭代器类型

	Node* _node;

	__TreeIterator(Node* node)
		:_node(node)
	{}
    //对普通迭代器来说,这是一个拷贝构造

	__TreeIterator(const Iterator& it)
		:_node(it._node)
	{}
    //对const迭代器来说,这就是一个单纯的构造,而不是拷贝构造
    //它可以支持普通迭代器去构造const迭代器

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &_node->_data;
	}

	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}
template<class T>
struct RBTreeNode
{
    //...
};
template<class K, class T, class KeyOfT>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
	typedef __TreeIterator<T, T*, T&> iterator; 
	typedef __TreeIterator<T, const T*, const T&> const_iterator;

    //...
};

​
//set
template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;

        //...

		//这里返回类型pair<iterator, bool>中的iterator实际是RBTree::const_iterator
		pair<iterator, bool> insert(const K& key)
		{
			pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
            //先用一个<普通迭代器,布尔值>的对象接收红黑树插入方法的返回值
			return pair<iterator, bool>(ret.first, ret.second);
            //再将对象中的普通迭代器通过构造函数构造为const迭代器
		}
	private:
		RBTree<K, K, SetKeyOfT> _t;
	};

 

3.模拟实现的完整代码

· RBTree.h

#pragma once
#include<iostream>
using namespace std;

//节点颜色
enum Colour
{
	RED,
	BLACK
};

//树节点
template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	
	T _data;
	Colour _col;

	RBTreeNode(const T& data)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_data(data)
		,_col(RED)
	{}
};

//迭代器
template<class T, class Ptr, class Ref>
struct __TreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef __TreeIterator<T, Ptr, Ref> Self;

	typedef __TreeIterator<T, T*, T&> Iterator;

	__TreeIterator(const Iterator& it)
		:_node(it._node)
	{}

	Node* _node;

	__TreeIterator(Node* node)
		:_node(node)
	{}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &_node->_data;
	}

	bool operator!=(const Self& s) const
	{
		return _node != s._node;
	}

	bool operator==(const Self& s) const
	{
		return _node != s._node;
	}

	Self& operator--()
	{
		if (_node->_left)
		{
			Node* subRight = _node->_left;
			while (subRight->_right)
			{
				subRight = subRight->_right;
			}

			_node = subRight;
		}
		else
		{
			// 孩子是父亲的右的那个节点
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}

			_node = parent;
		}

		return *this;
	}

	Self& operator++()
	{
		if (_node->_right)
		{
			// 右树的最左节点(最小节点)
			Node* subLeft = _node->_right;
			while (subLeft->_left)
			{
				subLeft = subLeft->_left;
			}

			_node = subLeft;
		}
		else
		{
			Node* cur = _node;
			Node* parent = cur->_parent;
			// 找孩子是父亲左的那个祖先节点,就是下一个要访问的节点
			while (parent && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;	
			}

			_node = parent;
		}

		return *this;
	}
};

//红黑树
template<class K, class T, class KeyOfT>
struct RBTree
{
	typedef RBTreeNode<T> Node;
public:
	typedef __TreeIterator<T, T*, T&> iterator;
	typedef __TreeIterator<T, const T*, const T&> const_iterator;

    //迭代器
	iterator begin()
	{
		Node* leftMin = _root;
		while (leftMin && leftMin->_left)
		{
			leftMin = leftMin->_left;
		}

		return iterator(leftMin);
	}
	iterator end()
	{
		return iterator(nullptr);
	}
	const_iterator begin() const
	{
		Node* leftMin = _root;
		while (leftMin && leftMin->_left)
		{
			leftMin = leftMin->_left;
		}

		return const_iterator(leftMin);
	}
	const_iterator end() const
	{
		return const_iterator(nullptr);
	}

    
    //查找
	Node* Find(const K& key)
	{
		Node* cur = _root;
		KeyOfT kot;
		while (cur)
		{
			if (kot(cur->_data) < key)
			{
				cur = cur->_right;
			}
			else if (kot(cur->_data) > key)
			{
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}

		return nullptr;
	}

    //插入
	pair<iterator, bool> Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}

		Node* parent = nullptr;
		Node* cur = _root;

		KeyOfT kot;
		while (cur)
		{
			if (kot(cur->_data) < kot(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_data) > kot(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}

		cur = new Node(data);
		cur->_col = RED;

		Node* newnode = cur;

		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}

		cur->_parent = parent;

		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else 
				{
					if (cur == parent->_left)
					{
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{

						RotateL(parent);
						RotateR(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}

					break;
				}
			}
			else
			{
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						grandfather->_col = RED;
						parent->_col = BLACK;
					}
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}

					break;
				}
			}
		}

		_root->_col = BLACK;

		return make_pair(iterator(newnode), true);
	}
    //左旋转
	void RotateL(Node* parent)
	{
		Node* cur = parent->_right;
		Node* curleft = cur->_left;

		parent->_right = curleft;
		if (curleft)
		{
			curleft->_parent = parent;
		}

		cur->_left = parent;

		Node* ppnode = parent->_parent;

		parent->_parent = cur;


		if (parent == _root)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;

			}

			cur->_parent = ppnode;
		}
	}
    //右旋转
	void RotateR(Node* parent)
	{
		Node* cur = parent->_left;
		Node* curright = cur->_right;

		parent->_left = curright;
		if (curright)
			curright->_parent = parent;

		Node* ppnode = parent->_parent;
		cur->_right = parent;
		parent->_parent = cur;

		if (ppnode == nullptr)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;
			}

			cur->_parent = ppnode;
		}
	}
	
    //查连续节点颜色
	bool CheckColour(Node* root, int blacknum, int benchmark)
	{
		if (root == nullptr)
		{
			if (blacknum != benchmark)
				return false;

			return true;
		}
		if (root->_col == BLACK)
		{
			++blacknum;
		}
		if (root->_col == RED && root->_parent && root->_parent->_col == RED)
		{
			cout << root->_kv.first << "出现连续红色节点" << endl;
			return false;
		}
		return CheckColour(root->_left, blacknum, benchmark)
			&& CheckColour(root->_right, blacknum, benchmark);
	}
    //验树平衡
	bool IsBalance()
	{
		return IsBalance(_root);
	}
	bool IsBalance(Node* root)
	{
		if (root == nullptr)
			return true;

		if (root->_col != BLACK)
		{
			return false;
		}
		int benchmark = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col == BLACK)
				++benchmark;

			cur = cur->_left;
		}

		return CheckColour(root, 0, benchmark);
	}

    //求树高度
	int Height()
	{
		return Height(_root);
	}
	int Height(Node* root)
	{
		if (root == nullptr)
			return 0;

		int leftHeight = Height(root->_left);
		int rightHeight = Height(root->_right);

		return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	}

private:
	Node* _root = nullptr;
};

· Map.h

#pragma once
#include"RBTree.h"

namespace CVE
{
	template<class K, class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;

		iterator begin()
		{
			return _t.begin();
		}

		iterator end()
		{
			return _t.end();
		}

		const_iterator begin() const
		{
			return _t.begin();
		}

		const_iterator end() const
		{
			return _t.end();
		}

		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = insert(make_pair(key, V()));
			return ret.first->second;
		}

		pair<iterator, bool> insert(const pair<K, V>& kv)
		{
			return _t.Insert(kv);
		}

	private:
		RBTree<K, pair<const K, V>, MapKeyOfT> _t;
	};
}

· Set.h

#pragma once
#include"RBTree.h"

namespace CVE
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;

		const_iterator begin() const
		{
			return _t.begin();
		}

		const_iterator end() const
		{
			return _t.end();
		}

		pair<iterator, bool> insert(const K& key)
		{
			pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
			return pair<iterator, bool>(ret.first, ret.second);
		}
	private:
		RBTree<K, K, SetKeyOfT> _t;
	};
}

 

补、multimap

        multimap相当于是map的不去重版本,<key,value>中key可以重复而不必唯一。

void test_multimap()
{
    multimap<string, string> m;	
	m.insert(pair<string, string>("peach", "桃子")); 
	m.insert(make_pair("banana", "香蕉"));
	m.insert(make_pair("banana", "香蕉"));

	cout << m.size() << endl;    //3
	cout << m.count("banana") << endl;    //2
 
	for (auto& e : m)
	{
		cout << e.first << "-->" << e.second << endl;
	}
    //banan-->香蕉
    //banan-->香蕉
    //peach-->桃子
 
	m.erase("banana"); //删除所有的"banana"
 
	multimap<string, string>::iterator it = m.begin();
	while (it != m.end())
	{
		cout << (*it).first << "-->" << (*it).second << endl;
		++it;
	}
    //peach-->桃子
 
	it = m.find("peach");
	cout << (*it).first << "-->" << (*it).second << endl; //peach-->桃子
}

补、multiset

        multiset相当于是set的不去重版本,可以存多个相同的key。

void test_multiset()
{
    // 仅排序 不去重
    multiset<int> s;
    s.insert(3);
    s.insert(5);
    s.insert(8);
    s.insert(7);
    s.insert(7);
    s.insert(9);
    s.insert(7);

    for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;

    // 返回中序第一个7
    auto pos = s.find(7);
    while (pos != s.end())
    {
        //*pos = 10;
        cout << *pos << " ";
        ++pos;
    }
    cout << endl;

    cout << s.count(7) << endl;

    auto ret = s.equal_range(6);//因为multiset中有多个相等的值,故更适配multiset
    auto itlow = ret.first;
    auto itup = ret.second;

    // [itlow, itup)
    // [7,7)
    cout << *itlow << endl;
    cout << *itup << endl;

    s.erase(itlow, itup);                     // 10 20 70 80 90

    for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;
}

 

补、一些精华笔试题

有效的括号

class Solution {
public:
    bool isValid(string s) {
        stack<char> st;

        for (auto ch : s)
        {
            if (ch == '(' || ch == '[' || ch == '{')
            {
                st.push(ch);
            }
            else
            {
                //数量不匹配
                if (st.empty())
                {
                    return false;
                }

                char topVal = st.top();
                st.pop();
                if((ch==']'&&topVal!='[')
                    || (ch == ')' && topVal != '(')
                    || (ch == '}' && topVal != '{'))
                {
                    return false;
                }
            }
        }
        return st.empty();
    }
};
class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        map<char, char> matchMap;
        matchMap['('] = ')';
        matchMap['['] = ']';
        matchMap['{'] = '}';

        for (auto ch : s)
        {
            if (matchMap.count(ch))
            {
                st.push(ch);
            }
            else
            {
                if (st.empty())
                {
                    return false;
                }
                char topVal = st.top();
                st.pop();
                if (matchMap[topVal]!=ch)
                {
                    return false;
                }
            }
        }
        return st.empty();
    }
};

 

随机链表的复制

class Solution{
public:
    Node * copyRandomList(Node * head) {
        map<Node*, Node*> nodeCopyMap;
        Node* copyhead = nullptr, *copytail=nullptr;

        //复制链表
        Node* cur = head;
        while (cur)
        {
            Node* copynode = new Node(cur->val);
            if (copytail == nullptr)
            {
                copyhead = copytail = copynode;
            }
            else
            {
                copytail->next = copynode;
                copytail = copytail->next;
            }
            
            nodeCopyMap[cur] = copynode;
            cur = cur->next; 
        }

        //控制random
        cur = head;
        Node* copy = copyhead;
        while (cur)
        {
            if (cur->random == nullptr)
            {
                copy->random = nullptr;
            }
            else
            {
                copy->random = nodeCopyMap[cur->random];
            }
            cur = cur->next;
            copy = copy->next;
        }

        return copyhead;
    }
};

 

两个数组的交集

// 法1:
//1.放进set去重
//2.遍历一个数据,判断在不在另一个
//(略)

//法2:
//找交集 - 找到之后:1、小的++,2、相等就是交集值且同时++ 
//差集 - 依次比较:1、小的就是差集,小的++,2、相等则同时++
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> s1(nums1.begin(), nums1.end());
        set<int> s2(nums2.begin(), nums2.end());

        vector<int> v;
        auto it1 = s1.begin();
        auto it2 = s2.begin();
        while (it1 != s1.end() && it2 != s2.end())
        {
            if (*it1 < *it2)
            {
                ++it1;
            }
            else if (*it1 > *it2)
            {
                ++it2;
            }
            else
            {
                v.push_back(*it1);
                ++it1; ++it2;
            }

        }
        return v;
    }
};

 

 前K个高频单词

//stable_sort

class Solution {
public:
    struct greater
    {
        bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2)
        {
            return kv1.second > kv2.second;
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int>countMap;
        //统计次数
        for (const auto& e : words)
        {
            countMap[e]++;
        }

        vector<pair<string, int>> kvVec(countMap.begin(), countMap.end());
        stable_sort(kvVec.begin(), kvVec.end(),greater());

        vector<string> ret;
        for (int i = 0; i < k; i++)
        {
            ret.push_back(kvVec[i].first);
        }
        return ret;
    }
};
// 控制仿函数
class Solution {
public:
    struct greater
    {
        bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2)
        {
            return kv1.second > kv2.second || (kv1.second == kv2.second && kv1.first < kv2.first);
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int>countMap;
        //统计次数
        for (const auto& e : words)
        {
            countMap[e]++;
        }

        vector<pair<string, int>> kvVec(countMap.begin(), countMap.end());
        stable_sort(kvVec.begin(), kvVec.end(), greater());

        vector<string> ret;
        for (int i = 0; i < k; i++)
        {
            ret.push_back(kvVec[i].first);
        }
        return ret;
    }
};
//通过multimap

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int>countMap;
        //统计次数
        for (const auto& e : words)
        {
            countMap[e]++;
        }

        multimap<int, string,greater<int>> sortMap;
        for (auto& kv : countMap)
        {
            sortMap.insert(make_pair(kv.second, kv.first));
        }

        vector<string> v;
        auto it = sortMap.begin();
        while (k--)
        {
            v.push_back(it->second);
            ++it;
        }
        return v;
    }
};

 

附、 rbtree、map、set源码

· rbtree

//rbtree

/*
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 *
 */

/* NOTE: This is an internal header file, included by other STL headers.
 *   You should not attempt to use it directly.
 */

#ifndef __SGI_STL_INTERNAL_TREE_H
#define __SGI_STL_INTERNAL_TREE_H

/*

Red-black tree class, designed for use in implementing STL
associative containers (set, multiset, map, and multimap). The
insertion and deletion algorithms are based on those in Cormen,
Leiserson, and Rivest, Introduction to Algorithms (MIT Press, 1990),
except that

(1) the header cell is maintained with links not only to the root
but also to the leftmost node of the tree, to enable constant time
begin(), and to the rightmost node of the tree, to enable linear time
performance when used with the generic set algorithms (set_union,
etc.);

(2) when a node being deleted has two children its successor node is
relinked into its place, rather than copied, so that the only
iterators invalidated are those referring to the deleted node.

*/

#include <stl_algobase.h>
#include <stl_alloc.h>
#include <stl_construct.h>
#include <stl_function.h>

__STL_BEGIN_NAMESPACE 

typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red = false;
const __rb_tree_color_type __rb_tree_black = true;

struct __rb_tree_node_base
{
  typedef __rb_tree_color_type color_type;
  typedef __rb_tree_node_base* base_ptr;

  color_type color; 
  base_ptr parent;
  base_ptr left;
  base_ptr right;

  static base_ptr minimum(base_ptr x)
  {
    while (x->left != 0) x = x->left;
    return x;
  }

  static base_ptr maximum(base_ptr x)
  {
    while (x->right != 0) x = x->right;
    return x;
  }
};

template <class Value>
struct __rb_tree_node : public __rb_tree_node_base
{
  typedef __rb_tree_node<Value>* link_type;
  Value value_field;
};


struct __rb_tree_base_iterator
{
  typedef __rb_tree_node_base::base_ptr base_ptr;
  typedef bidirectional_iterator_tag iterator_category;
  typedef ptrdiff_t difference_type;
  base_ptr node;

  void increment()
  {
    if (node->right != 0) {
      node = node->right;
      while (node->left != 0)
        node = node->left;
    }
    else {
      base_ptr y = node->parent;
      while (node == y->right) {
        node = y;
        y = y->parent;
      }
      if (node->right != y)
        node = y;
    }
  }

  void decrement()
  {
    if (node->color == __rb_tree_red &&
        node->parent->parent == node)
      node = node->right;
    else if (node->left != 0) {
      base_ptr y = node->left;
      while (y->right != 0)
        y = y->right;
      node = y;
    }
    else {
      base_ptr y = node->parent;
      while (node == y->left) {
        node = y;
        y = y->parent;
      }
      node = y;
    }
  }
};

template <class Value, class Ref, class Ptr>
struct __rb_tree_iterator : public __rb_tree_base_iterator
{
  typedef Value value_type;
  typedef Ref reference;
  typedef Ptr pointer;
  typedef __rb_tree_iterator<Value, Value&, Value*>             iterator;
  typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator;
  typedef __rb_tree_iterator<Value, Ref, Ptr>                   self;
  typedef __rb_tree_node<Value>* link_type;

  __rb_tree_iterator() {}
  __rb_tree_iterator(link_type x) { node = x; }
  __rb_tree_iterator(const iterator& it) { node = it.node; }

  reference operator*() const { return link_type(node)->value_field; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */

  self& operator++() { increment(); return *this; }
  self operator++(int) {
    self tmp = *this;
    increment();
    return tmp;
  }
    
  self& operator--() { decrement(); return *this; }
  self operator--(int) {
    self tmp = *this;
    decrement();
    return tmp;
  }
};

inline bool operator==(const __rb_tree_base_iterator& x,
                       const __rb_tree_base_iterator& y) {
  return x.node == y.node;
}

inline bool operator!=(const __rb_tree_base_iterator& x,
                       const __rb_tree_base_iterator& y) {
  return x.node != y.node;
}

#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION

inline bidirectional_iterator_tag
iterator_category(const __rb_tree_base_iterator&) {
  return bidirectional_iterator_tag();
}

inline __rb_tree_base_iterator::difference_type*
distance_type(const __rb_tree_base_iterator&) {
  return (__rb_tree_base_iterator::difference_type*) 0;
}

template <class Value, class Ref, class Ptr>
inline Value* value_type(const __rb_tree_iterator<Value, Ref, Ptr>&) {
  return (Value*) 0;
}

#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */

inline void 
__rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
  __rb_tree_node_base* y = x->right;
  x->right = y->left;
  if (y->left !=0)
    y->left->parent = x;
  y->parent = x->parent;

  if (x == root)
    root = y;
  else if (x == x->parent->left)
    x->parent->left = y;
  else
    x->parent->right = y;
  y->left = x;
  x->parent = y;
}

inline void 
__rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
  __rb_tree_node_base* y = x->left;
  x->left = y->right;
  if (y->right != 0)
    y->right->parent = x;
  y->parent = x->parent;

  if (x == root)
    root = y;
  else if (x == x->parent->right)
    x->parent->right = y;
  else
    x->parent->left = y;
  y->right = x;
  x->parent = y;
}

inline void 
__rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
  x->color = __rb_tree_red;
  while (x != root && x->parent->color == __rb_tree_red) {
    if (x->parent == x->parent->parent->left) {
      __rb_tree_node_base* y = x->parent->parent->right;
      if (y && y->color == __rb_tree_red) {
        x->parent->color = __rb_tree_black;
        y->color = __rb_tree_black;
        x->parent->parent->color = __rb_tree_red;
        x = x->parent->parent;
      }
      else {
        if (x == x->parent->right) {
          x = x->parent;
          __rb_tree_rotate_left(x, root);
        }
        x->parent->color = __rb_tree_black;
        x->parent->parent->color = __rb_tree_red;
        __rb_tree_rotate_right(x->parent->parent, root);
      }
    }
    else {
      __rb_tree_node_base* y = x->parent->parent->left;
      if (y && y->color == __rb_tree_red) {
        x->parent->color = __rb_tree_black;
        y->color = __rb_tree_black;
        x->parent->parent->color = __rb_tree_red;
        x = x->parent->parent;
      }
      else {
        if (x == x->parent->left) {
          x = x->parent;
          __rb_tree_rotate_right(x, root);
        }
        x->parent->color = __rb_tree_black;
        x->parent->parent->color = __rb_tree_red;
        __rb_tree_rotate_left(x->parent->parent, root);
      }
    }
  }
  root->color = __rb_tree_black;
}

inline __rb_tree_node_base*
__rb_tree_rebalance_for_erase(__rb_tree_node_base* z,
                              __rb_tree_node_base*& root,
                              __rb_tree_node_base*& leftmost,
                              __rb_tree_node_base*& rightmost)
{
  __rb_tree_node_base* y = z;
  __rb_tree_node_base* x = 0;
  __rb_tree_node_base* x_parent = 0;
  if (y->left == 0)             // z has at most one non-null child. y == z.
    x = y->right;               // x might be null.
  else
    if (y->right == 0)          // z has exactly one non-null child.  y == z.
      x = y->left;              // x is not null.
    else {                      // z has two non-null children.  Set y to
      y = y->right;             //   z's successor.  x might be null.
      while (y->left != 0)
        y = y->left;
      x = y->right;
    }
  if (y != z) {                 // relink y in place of z.  y is z's successor
    z->left->parent = y; 
    y->left = z->left;
    if (y != z->right) {
      x_parent = y->parent;
      if (x) x->parent = y->parent;
      y->parent->left = x;      // y must be a left child
      y->right = z->right;
      z->right->parent = y;
    }
    else
      x_parent = y;  
    if (root == z)
      root = y;
    else if (z->parent->left == z)
      z->parent->left = y;
    else 
      z->parent->right = y;
    y->parent = z->parent;
    __STD::swap(y->color, z->color);
    y = z;
    // y now points to node to be actually deleted
  }
  else {                        // y == z
    x_parent = y->parent;
    if (x) x->parent = y->parent;   
    if (root == z)
      root = x;
    else 
      if (z->parent->left == z)
        z->parent->left = x;
      else
        z->parent->right = x;
    if (leftmost == z) 
      if (z->right == 0)        // z->left must be null also
        leftmost = z->parent;
    // makes leftmost == header if z == root
      else
        leftmost = __rb_tree_node_base::minimum(x);
    if (rightmost == z)  
      if (z->left == 0)         // z->right must be null also
        rightmost = z->parent;  
    // makes rightmost == header if z == root
      else                      // x == z->left
        rightmost = __rb_tree_node_base::maximum(x);
  }
  if (y->color != __rb_tree_red) { 
    while (x != root && (x == 0 || x->color == __rb_tree_black))
      if (x == x_parent->left) {
        __rb_tree_node_base* w = x_parent->right;
        if (w->color == __rb_tree_red) {
          w->color = __rb_tree_black;
          x_parent->color = __rb_tree_red;
          __rb_tree_rotate_left(x_parent, root);
          w = x_parent->right;
        }
        if ((w->left == 0 || w->left->color == __rb_tree_black) &&
            (w->right == 0 || w->right->color == __rb_tree_black)) {
          w->color = __rb_tree_red;
          x = x_parent;
          x_parent = x_parent->parent;
        } else {
          if (w->right == 0 || w->right->color == __rb_tree_black) {
            if (w->left) w->left->color = __rb_tree_black;
            w->color = __rb_tree_red;
            __rb_tree_rotate_right(w, root);
            w = x_parent->right;
          }
          w->color = x_parent->color;
          x_parent->color = __rb_tree_black;
          if (w->right) w->right->color = __rb_tree_black;
          __rb_tree_rotate_left(x_parent, root);
          break;
        }
      } else {                  // same as above, with right <-> left.
        __rb_tree_node_base* w = x_parent->left;
        if (w->color == __rb_tree_red) {
          w->color = __rb_tree_black;
          x_parent->color = __rb_tree_red;
          __rb_tree_rotate_right(x_parent, root);
          w = x_parent->left;
        }
        if ((w->right == 0 || w->right->color == __rb_tree_black) &&
            (w->left == 0 || w->left->color == __rb_tree_black)) {
          w->color = __rb_tree_red;
          x = x_parent;
          x_parent = x_parent->parent;
        } else {
          if (w->left == 0 || w->left->color == __rb_tree_black) {
            if (w->right) w->right->color = __rb_tree_black;
            w->color = __rb_tree_red;
            __rb_tree_rotate_left(w, root);
            w = x_parent->left;
          }
          w->color = x_parent->color;
          x_parent->color = __rb_tree_black;
          if (w->left) w->left->color = __rb_tree_black;
          __rb_tree_rotate_right(x_parent, root);
          break;
        }
      }
    if (x) x->color = __rb_tree_black;
  }
  return y;
}

template <class Key, class Value, class KeyOfValue, class Compare,
          class Alloc = alloc>
class rb_tree {
protected:
  typedef void* void_pointer;
  typedef __rb_tree_node_base* base_ptr;
  typedef __rb_tree_node<Value> rb_tree_node;
  typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;
  typedef __rb_tree_color_type color_type;
public:
  typedef Key key_type;
  typedef Value value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef rb_tree_node* link_type;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
protected:
  link_type get_node() { return rb_tree_node_allocator::allocate(); }
  void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }

  link_type create_node(const value_type& x) {
    link_type tmp = get_node();
    __STL_TRY {
      construct(&tmp->value_field, x);
    }
    __STL_UNWIND(put_node(tmp));
    return tmp;
  }

  link_type clone_node(link_type x) {
    link_type tmp = create_node(x->value_field);
    tmp->color = x->color;
    tmp->left = 0;
    tmp->right = 0;
    return tmp;
  }

  void destroy_node(link_type p) {
    destroy(&p->value_field);
    put_node(p);
  }

protected:
  size_type node_count; // keeps track of size of tree
  link_type header;  
  Compare key_compare;

  link_type& root() const { return (link_type&) header->parent; }
  link_type& leftmost() const { return (link_type&) header->left; }
  link_type& rightmost() const { return (link_type&) header->right; }

  static link_type& left(link_type x) { return (link_type&)(x->left); }
  static link_type& right(link_type x) { return (link_type&)(x->right); }
  static link_type& parent(link_type x) { return (link_type&)(x->parent); }
  static reference value(link_type x) { return x->value_field; }
  static const Key& key(link_type x) { return KeyOfValue()(value(x)); }
  static color_type& color(link_type x) { return (color_type&)(x->color); }

  static link_type& left(base_ptr x) { return (link_type&)(x->left); }
  static link_type& right(base_ptr x) { return (link_type&)(x->right); }
  static link_type& parent(base_ptr x) { return (link_type&)(x->parent); }
  static reference value(base_ptr x) { return ((link_type)x)->value_field; }
  static const Key& key(base_ptr x) { return KeyOfValue()(value(link_type(x)));} 
  static color_type& color(base_ptr x) { return (color_type&)(link_type(x)->color); }

  static link_type minimum(link_type x) { 
    return (link_type)  __rb_tree_node_base::minimum(x);
  }
  static link_type maximum(link_type x) {
    return (link_type) __rb_tree_node_base::maximum(x);
  }

public:
  typedef __rb_tree_iterator<value_type, reference, pointer> iterator;
  typedef __rb_tree_iterator<value_type, const_reference, const_pointer> 
          const_iterator;

#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
  typedef reverse_iterator<const_iterator> const_reverse_iterator;
  typedef reverse_iterator<iterator> reverse_iterator;
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
  typedef reverse_bidirectional_iterator<iterator, value_type, reference,
                                         difference_type>
          reverse_iterator; 
  typedef reverse_bidirectional_iterator<const_iterator, value_type,
                                         const_reference, difference_type>
          const_reverse_iterator;
#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ 
private:
  iterator __insert(base_ptr x, base_ptr y, const value_type& v);
  link_type __copy(link_type x, link_type p);
  void __erase(link_type x);
  void init() {
    header = get_node();
    color(header) = __rb_tree_red; // used to distinguish header from 
                                   // root, in iterator.operator++
    root() = 0;
    leftmost() = header;
    rightmost() = header;
  }
public:
                                // allocation/deallocation
  rb_tree(const Compare& comp = Compare())
    : node_count(0), key_compare(comp) { init(); }

  rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) 
    : node_count(0), key_compare(x.key_compare)
  { 
    header = get_node();
    color(header) = __rb_tree_red;
    if (x.root() == 0) {
      root() = 0;
      leftmost() = header;
      rightmost() = header;
    }
    else {
      __STL_TRY {
        root() = __copy(x.root(), header);
      }
      __STL_UNWIND(put_node(header));
      leftmost() = minimum(root());
      rightmost() = maximum(root());
    }
    node_count = x.node_count;
  }
  ~rb_tree() {
    clear();
    put_node(header);
  }
  rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& 
  operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x);

public:    
                                // accessors:
  Compare key_comp() const { return key_compare; }
  iterator begin() { return leftmost(); }
  const_iterator begin() const { return leftmost(); }
  iterator end() { return header; }
  const_iterator end() const { return header; }
  reverse_iterator rbegin() { return reverse_iterator(end()); }
  const_reverse_iterator rbegin() const { 
    return const_reverse_iterator(end()); 
  }
  reverse_iterator rend() { return reverse_iterator(begin()); }
  const_reverse_iterator rend() const { 
    return const_reverse_iterator(begin());
  } 
  bool empty() const { return node_count == 0; }
  size_type size() const { return node_count; }
  size_type max_size() const { return size_type(-1); }

  void swap(rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& t) {
    __STD::swap(header, t.header);
    __STD::swap(node_count, t.node_count);
    __STD::swap(key_compare, t.key_compare);
  }
    
public:
                                // insert/erase
  pair<iterator,bool> insert_unique(const value_type& x);
  iterator insert_equal(const value_type& x);

  iterator insert_unique(iterator position, const value_type& x);
  iterator insert_equal(iterator position, const value_type& x);

#ifdef __STL_MEMBER_TEMPLATES  
  template <class InputIterator>
  void insert_unique(InputIterator first, InputIterator last);
  template <class InputIterator>
  void insert_equal(InputIterator first, InputIterator last);
#else /* __STL_MEMBER_TEMPLATES */
  void insert_unique(const_iterator first, const_iterator last);
  void insert_unique(const value_type* first, const value_type* last);
  void insert_equal(const_iterator first, const_iterator last);
  void insert_equal(const value_type* first, const value_type* last);
#endif /* __STL_MEMBER_TEMPLATES */

  void erase(iterator position);
  size_type erase(const key_type& x);
  void erase(iterator first, iterator last);
  void erase(const key_type* first, const key_type* last);
  void clear() {
    if (node_count != 0) {
      __erase(root());
      leftmost() = header;
      root() = 0;
      rightmost() = header;
      node_count = 0;
    }
  }      

public:
                                // set operations:
  iterator find(const key_type& x);
  const_iterator find(const key_type& x) const;
  size_type count(const key_type& x) const;
  iterator lower_bound(const key_type& x);
  const_iterator lower_bound(const key_type& x) const;
  iterator upper_bound(const key_type& x);
  const_iterator upper_bound(const key_type& x) const;
  pair<iterator,iterator> equal_range(const key_type& x);
  pair<const_iterator, const_iterator> equal_range(const key_type& x) const;

public:
                                // Debugging.
  bool __rb_verify() const;
};

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline bool operator==(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, 
                       const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) {
  return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline bool operator<(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, 
                      const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) {
  return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}

#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline void swap(rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, 
                 rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) {
  x.swap(y);
}

#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */


template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::
operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) {
  if (this != &x) {
                                // Note that Key may be a constant type.
    clear();
    node_count = 0;
    key_compare = x.key_compare;        
    if (x.root() == 0) {
      root() = 0;
      leftmost() = header;
      rightmost() = header;
    }
    else {
      root() = __copy(x.root(), header);
      leftmost() = minimum(root());
      rightmost() = maximum(root());
      node_count = x.node_count;
    }
  }
  return *this;
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::
__insert(base_ptr x_, base_ptr y_, const Value& v) {
  link_type x = (link_type) x_;
  link_type y = (link_type) y_;
  link_type z;

  if (y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))) {
    z = create_node(v);
    left(y) = z;                // also makes leftmost() = z when y == header
    if (y == header) {
      root() = z;
      rightmost() = z;
    }
    else if (y == leftmost())
      leftmost() = z;           // maintain leftmost() pointing to min node
  }
  else {
    z = create_node(v);
    right(y) = z;
    if (y == rightmost())
      rightmost() = z;          // maintain rightmost() pointing to max node
  }
  parent(z) = y;
  left(z) = 0;
  right(z) = 0;
  __rb_tree_rebalance(z, header->parent);
  ++node_count;
  return iterator(z);
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_equal(const Value& v)
{
  link_type y = header;
  link_type x = root();
  while (x != 0) {
    y = x;
    x = key_compare(KeyOfValue()(v), key(x)) ? left(x) : right(x);
  }
  return __insert(x, y, v);
}


template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const Value& v)
{
  link_type y = header;
  link_type x = root();
  bool comp = true;
  while (x != 0) {
    y = x;
    comp = key_compare(KeyOfValue()(v), key(x));
    x = comp ? left(x) : right(x);
  }
  iterator j = iterator(y);   
  if (comp)
    if (j == begin())     
      return pair<iterator,bool>(__insert(x, y, v), true);
    else
      --j;
  if (key_compare(key(j.node), KeyOfValue()(v)))
    return pair<iterator,bool>(__insert(x, y, v), true);
  return pair<iterator,bool>(j, false);
}


template <class Key, class Val, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::iterator 
rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::insert_unique(iterator position,
                                                             const Val& v) {
  if (position.node == header->left) // begin()
    if (size() > 0 && key_compare(KeyOfValue()(v), key(position.node)))
      return __insert(position.node, position.node, v);
  // first argument just needs to be non-null 
    else
      return insert_unique(v).first;
  else if (position.node == header) // end()
    if (key_compare(key(rightmost()), KeyOfValue()(v)))
      return __insert(0, rightmost(), v);
    else
      return insert_unique(v).first;
  else {
    iterator before = position;
    --before;
    if (key_compare(key(before.node), KeyOfValue()(v))
        && key_compare(KeyOfValue()(v), key(position.node)))
      if (right(before.node) == 0)
        return __insert(0, before.node, v); 
      else
        return __insert(position.node, position.node, v);
    // first argument just needs to be non-null 
    else
      return insert_unique(v).first;
  }
}

template <class Key, class Val, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::iterator 
rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::insert_equal(iterator position,
                                                            const Val& v) {
  if (position.node == header->left) // begin()
    if (size() > 0 && key_compare(KeyOfValue()(v), key(position.node)))
      return __insert(position.node, position.node, v);
  // first argument just needs to be non-null 
    else
      return insert_equal(v);
  else if (position.node == header) // end()
    if (!key_compare(KeyOfValue()(v), key(rightmost())))
      return __insert(0, rightmost(), v);
    else
      return insert_equal(v);
  else {
    iterator before = position;
    --before;
    if (!key_compare(KeyOfValue()(v), key(before.node))
        && !key_compare(key(position.node), KeyOfValue()(v)))
      if (right(before.node) == 0)
        return __insert(0, before.node, v); 
      else
        return __insert(position.node, position.node, v);
    // first argument just needs to be non-null 
    else
      return insert_equal(v);
  }
}

#ifdef __STL_MEMBER_TEMPLATES  

template <class K, class V, class KoV, class Cmp, class Al> template<class II>
void rb_tree<K, V, KoV, Cmp, Al>::insert_equal(II first, II last) {
  for ( ; first != last; ++first)
    insert_equal(*first);
}

template <class K, class V, class KoV, class Cmp, class Al> template<class II>
void rb_tree<K, V, KoV, Cmp, Al>::insert_unique(II first, II last) {
  for ( ; first != last; ++first)
    insert_unique(*first);
}

#else /* __STL_MEMBER_TEMPLATES */

template <class K, class V, class KoV, class Cmp, class Al>
void
rb_tree<K, V, KoV, Cmp, Al>::insert_equal(const V* first, const V* last) {
  for ( ; first != last; ++first)
    insert_equal(*first);
}

template <class K, class V, class KoV, class Cmp, class Al>
void
rb_tree<K, V, KoV, Cmp, Al>::insert_equal(const_iterator first,
                                          const_iterator last) {
  for ( ; first != last; ++first)
    insert_equal(*first);
}

template <class K, class V, class KoV, class Cmp, class A>
void 
rb_tree<K, V, KoV, Cmp, A>::insert_unique(const V* first, const V* last) {
  for ( ; first != last; ++first)
    insert_unique(*first);
}

template <class K, class V, class KoV, class Cmp, class A>
void 
rb_tree<K, V, KoV, Cmp, A>::insert_unique(const_iterator first,
                                          const_iterator last) {
  for ( ; first != last; ++first)
    insert_unique(*first);
}

#endif /* __STL_MEMBER_TEMPLATES */
         
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline void
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator position) {
  link_type y = (link_type) __rb_tree_rebalance_for_erase(position.node,
                                                          header->parent,
                                                          header->left,
                                                          header->right);
  destroy_node(y);
  --node_count;
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::size_type 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(const Key& x) {
  pair<iterator,iterator> p = equal_range(x);
  size_type n = 0;
  distance(p.first, p.second, n);
  erase(p.first, p.second);
  return n;
}

template <class K, class V, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<K, V, KeyOfValue, Compare, Alloc>::link_type 
rb_tree<K, V, KeyOfValue, Compare, Alloc>::__copy(link_type x, link_type p) {
                                // structural copy.  x and p must be non-null.
  link_type top = clone_node(x);
  top->parent = p;
 
  __STL_TRY {
    if (x->right)
      top->right = __copy(right(x), top);
    p = top;
    x = left(x);

    while (x != 0) {
      link_type y = clone_node(x);
      p->left = y;
      y->parent = p;
      if (x->right)
        y->right = __copy(right(x), y);
      p = y;
      x = left(x);
    }
  }
  __STL_UNWIND(__erase(top));

  return top;
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__erase(link_type x) {
                                // erase without rebalancing
  while (x != 0) {
    __erase(right(x));
    link_type y = left(x);
    destroy_node(x);
    x = y;
  }
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator first, 
                                                            iterator last) {
  if (first == begin() && last == end())
    clear();
  else
    while (first != last) erase(first++);
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(const Key* first, 
                                                            const Key* last) {
  while (first != last) erase(*first++);
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k) {
  link_type y = header;        // Last node which is not less than k. 
  link_type x = root();        // Current node. 

  while (x != 0) 
    if (!key_compare(key(x), k))
      y = x, x = left(x);
    else
      x = right(x);

  iterator j = iterator(y);   
  return (j == end() || key_compare(k, key(j.node))) ? end() : j;
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k) const {
  link_type y = header; /* Last node which is not less than k. */
  link_type x = root(); /* Current node. */

  while (x != 0) {
    if (!key_compare(key(x), k))
      y = x, x = left(x);
    else
      x = right(x);
  }
  const_iterator j = const_iterator(y);   
  return (j == end() || key_compare(k, key(j.node))) ? end() : j;
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::size_type 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::count(const Key& k) const {
  pair<const_iterator, const_iterator> p = equal_range(k);
  size_type n = 0;
  distance(p.first, p.second, n);
  return n;
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::lower_bound(const Key& k) {
  link_type y = header; /* Last node which is not less than k. */
  link_type x = root(); /* Current node. */

  while (x != 0) 
    if (!key_compare(key(x), k))
      y = x, x = left(x);
    else
      x = right(x);

  return iterator(y);
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::lower_bound(const Key& k) const {
  link_type y = header; /* Last node which is not less than k. */
  link_type x = root(); /* Current node. */

  while (x != 0) 
    if (!key_compare(key(x), k))
      y = x, x = left(x);
    else
      x = right(x);

  return const_iterator(y);
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::upper_bound(const Key& k) {
  link_type y = header; /* Last node which is greater than k. */
  link_type x = root(); /* Current node. */

   while (x != 0) 
     if (key_compare(k, key(x)))
       y = x, x = left(x);
     else
       x = right(x);

   return iterator(y);
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::upper_bound(const Key& k) const {
  link_type y = header; /* Last node which is greater than k. */
  link_type x = root(); /* Current node. */

   while (x != 0) 
     if (key_compare(k, key(x)))
       y = x, x = left(x);
     else
       x = right(x);

   return const_iterator(y);
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator,
            typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::equal_range(const Key& k) {
  return pair<iterator, iterator>(lower_bound(k), upper_bound(k));
}

template <class Key, class Value, class KoV, class Compare, class Alloc>
inline pair<typename rb_tree<Key, Value, KoV, Compare, Alloc>::const_iterator,
            typename rb_tree<Key, Value, KoV, Compare, Alloc>::const_iterator>
rb_tree<Key, Value, KoV, Compare, Alloc>::equal_range(const Key& k) const {
  return pair<const_iterator,const_iterator>(lower_bound(k), upper_bound(k));
}

inline int __black_count(__rb_tree_node_base* node, __rb_tree_node_base* root)
{
  if (node == 0)
    return 0;
  else {
    int bc = node->color == __rb_tree_black ? 1 : 0;
    if (node == root)
      return bc;
    else
      return bc + __black_count(node->parent, root);
  }
}

template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
bool 
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__rb_verify() const
{
  if (node_count == 0 || begin() == end())
    return node_count == 0 && begin() == end() &&
      header->left == header && header->right == header;
  
  int len = __black_count(leftmost(), root());
  for (const_iterator it = begin(); it != end(); ++it) {
    link_type x = (link_type) it.node;
    link_type L = left(x);
    link_type R = right(x);

    if (x->color == __rb_tree_red)
      if ((L && L->color == __rb_tree_red) ||
          (R && R->color == __rb_tree_red))
        return false;

    if (L && key_compare(key(x), key(L)))
      return false;
    if (R && key_compare(key(R), key(x)))
      return false;

    if (!L && !R && __black_count(x, root()) != len)
      return false;
  }

  if (leftmost() != __rb_tree_node_base::minimum(root()))
    return false;
  if (rightmost() != __rb_tree_node_base::maximum(root()))
    return false;

  return true;
}

__STL_END_NAMESPACE 

#endif /* __SGI_STL_INTERNAL_TREE_H */

// Local Variables:
// mode:C++
// End:

· map

//map

/*
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 */

/* NOTE: This is an internal header file, included by other STL headers.
 *   You should not attempt to use it directly.
 */

#ifndef __SGI_STL_INTERNAL_MAP_H
#define __SGI_STL_INTERNAL_MAP_H

__STL_BEGIN_NAMESPACE

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1174
#endif

#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
#else
template <class Key, class T, class Compare, class Alloc = alloc>
#endif
class map {
public:

// typedefs:

  typedef Key key_type;
  typedef T data_type;
  typedef T mapped_type;
  typedef pair<const Key, T> value_type;
  typedef Compare key_compare;
    
  class value_compare
    : public binary_function<value_type, value_type, bool> {
  friend class map<Key, T, Compare, Alloc>;
  protected :
    Compare comp;
    value_compare(Compare c) : comp(c) {}
  public:
    bool operator()(const value_type& x, const value_type& y) const {
      return comp(x.first, y.first);
    }
  };

private:
  typedef rb_tree<key_type, value_type, 
                  select1st<value_type>, key_compare, Alloc> rep_type;
  rep_type t;  // red-black tree representing map
public:
  typedef typename rep_type::pointer pointer;
  typedef typename rep_type::const_pointer const_pointer;
  typedef typename rep_type::reference reference;
  typedef typename rep_type::const_reference const_reference;
  typedef typename rep_type::iterator iterator;
  typedef typename rep_type::const_iterator const_iterator;
  typedef typename rep_type::reverse_iterator reverse_iterator;
  typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
  typedef typename rep_type::size_type size_type;
  typedef typename rep_type::difference_type difference_type;

  // allocation/deallocation

  map() : t(Compare()) {}
  explicit map(const Compare& comp) : t(comp) {}

#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  map(InputIterator first, InputIterator last)
    : t(Compare()) { t.insert_unique(first, last); }

  template <class InputIterator>
  map(InputIterator first, InputIterator last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }
#else
  map(const value_type* first, const value_type* last)
    : t(Compare()) { t.insert_unique(first, last); }
  map(const value_type* first, const value_type* last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }

  map(const_iterator first, const_iterator last)
    : t(Compare()) { t.insert_unique(first, last); }
  map(const_iterator first, const_iterator last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }
#endif /* __STL_MEMBER_TEMPLATES */

  map(const map<Key, T, Compare, Alloc>& x) : t(x.t) {}
  map<Key, T, Compare, Alloc>& operator=(const map<Key, T, Compare, Alloc>& x)
  {
    t = x.t;
    return *this; 
  }

  // accessors:

  key_compare key_comp() const { return t.key_comp(); }
  value_compare value_comp() const { return value_compare(t.key_comp()); }
  iterator begin() { return t.begin(); }
  const_iterator begin() const { return t.begin(); }
  iterator end() { return t.end(); }
  const_iterator end() const { return t.end(); }
  reverse_iterator rbegin() { return t.rbegin(); }
  const_reverse_iterator rbegin() const { return t.rbegin(); }
  reverse_iterator rend() { return t.rend(); }
  const_reverse_iterator rend() const { return t.rend(); }
  bool empty() const { return t.empty(); }
  size_type size() const { return t.size(); }
  size_type max_size() const { return t.max_size(); }
  T& operator[](const key_type& k) {
    return (*((insert(value_type(k, T()))).first)).second;
  }
  void swap(map<Key, T, Compare, Alloc>& x) { t.swap(x.t); }

  // insert/erase

  pair<iterator,bool> insert(const value_type& x) { return t.insert_unique(x); }
  iterator insert(iterator position, const value_type& x) {
    return t.insert_unique(position, x);
  }
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  void insert(InputIterator first, InputIterator last) {
    t.insert_unique(first, last);
  }
#else
  void insert(const value_type* first, const value_type* last) {
    t.insert_unique(first, last);
  }
  void insert(const_iterator first, const_iterator last) {
    t.insert_unique(first, last);
  }
#endif /* __STL_MEMBER_TEMPLATES */

  void erase(iterator position) { t.erase(position); }
  size_type erase(const key_type& x) { return t.erase(x); }
  void erase(iterator first, iterator last) { t.erase(first, last); }
  void clear() { t.clear(); }

  // map operations:

  iterator find(const key_type& x) { return t.find(x); }
  const_iterator find(const key_type& x) const { return t.find(x); }
  size_type count(const key_type& x) const { return t.count(x); }
  iterator lower_bound(const key_type& x) {return t.lower_bound(x); }
  const_iterator lower_bound(const key_type& x) const {
    return t.lower_bound(x); 
  }
  iterator upper_bound(const key_type& x) {return t.upper_bound(x); }
  const_iterator upper_bound(const key_type& x) const {
    return t.upper_bound(x); 
  }
  
  pair<iterator,iterator> equal_range(const key_type& x) {
    return t.equal_range(x);
  }
  pair<const_iterator,const_iterator> equal_range(const key_type& x) const {
    return t.equal_range(x);
  }
  friend bool operator== __STL_NULL_TMPL_ARGS (const map&, const map&);
  friend bool operator< __STL_NULL_TMPL_ARGS (const map&, const map&);
};

template <class Key, class T, class Compare, class Alloc>
inline bool operator==(const map<Key, T, Compare, Alloc>& x, 
                       const map<Key, T, Compare, Alloc>& y) {
  return x.t == y.t;
}

template <class Key, class T, class Compare, class Alloc>
inline bool operator<(const map<Key, T, Compare, Alloc>& x, 
                      const map<Key, T, Compare, Alloc>& y) {
  return x.t < y.t;
}

#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER

template <class Key, class T, class Compare, class Alloc>
inline void swap(map<Key, T, Compare, Alloc>& x, 
                 map<Key, T, Compare, Alloc>& y) {
  x.swap(y);
}

#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma reset woff 1174
#endif

__STL_END_NAMESPACE

#endif /* __SGI_STL_INTERNAL_MAP_H */

// Local Variables:
// mode:C++
// End:

· set

//set

/*
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 */

/* NOTE: This is an internal header file, included by other STL headers.
 *   You should not attempt to use it directly.
 */

#ifndef __SGI_STL_INTERNAL_SET_H
#define __SGI_STL_INTERNAL_SET_H

__STL_BEGIN_NAMESPACE

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1174
#endif

#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <class Key, class Compare = less<Key>, class Alloc = alloc>
#else
template <class Key, class Compare, class Alloc = alloc>
#endif
class set {
public:
  // typedefs:

  typedef Key key_type;
  typedef Key value_type;
  typedef Compare key_compare;
  typedef Compare value_compare;
private:
  typedef rb_tree<key_type, value_type, 
                  identity<value_type>, key_compare, Alloc> rep_type;
  rep_type t;  // red-black tree representing set
public:
  typedef typename rep_type::const_pointer pointer;
  typedef typename rep_type::const_pointer const_pointer;
  typedef typename rep_type::const_reference reference;
  typedef typename rep_type::const_reference const_reference;
  typedef typename rep_type::const_iterator iterator;
  typedef typename rep_type::const_iterator const_iterator;
  typedef typename rep_type::const_reverse_iterator reverse_iterator;
  typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
  typedef typename rep_type::size_type size_type;
  typedef typename rep_type::difference_type difference_type;

  // allocation/deallocation

  set() : t(Compare()) {}
  explicit set(const Compare& comp) : t(comp) {}

#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  set(InputIterator first, InputIterator last)
    : t(Compare()) { t.insert_unique(first, last); }

  template <class InputIterator>
  set(InputIterator first, InputIterator last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }
#else
  set(const value_type* first, const value_type* last) 
    : t(Compare()) { t.insert_unique(first, last); }
  set(const value_type* first, const value_type* last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }

  set(const_iterator first, const_iterator last)
    : t(Compare()) { t.insert_unique(first, last); }
  set(const_iterator first, const_iterator last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }
#endif /* __STL_MEMBER_TEMPLATES */

  set(const set<Key, Compare, Alloc>& x) : t(x.t) {}
  set<Key, Compare, Alloc>& operator=(const set<Key, Compare, Alloc>& x) { 
    t = x.t; 
    return *this;
  }

  // accessors:

  key_compare key_comp() const { return t.key_comp(); }
  value_compare value_comp() const { return t.key_comp(); }
  iterator begin() const { return t.begin(); }
  iterator end() const { return t.end(); }
  reverse_iterator rbegin() const { return t.rbegin(); } 
  reverse_iterator rend() const { return t.rend(); }
  bool empty() const { return t.empty(); }
  size_type size() const { return t.size(); }
  size_type max_size() const { return t.max_size(); }
  void swap(set<Key, Compare, Alloc>& x) { t.swap(x.t); }

  // insert/erase
  typedef  pair<iterator, bool> pair_iterator_bool; 
  pair<iterator,bool> insert(const value_type& x) { 
    pair<typename rep_type::iterator, bool> p = t.insert_unique(x); 
    return pair<iterator, bool>(p.first, p.second);
  }
  iterator insert(iterator position, const value_type& x) {
    typedef typename rep_type::iterator rep_iterator;
    return t.insert_unique((rep_iterator&)position, x);
  }
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  void insert(InputIterator first, InputIterator last) {
    t.insert_unique(first, last);
  }
#else
  void insert(const_iterator first, const_iterator last) {
    t.insert_unique(first, last);
  }
  void insert(const value_type* first, const value_type* last) {
    t.insert_unique(first, last);
  }
#endif /* __STL_MEMBER_TEMPLATES */
  void erase(iterator position) { 
    typedef typename rep_type::iterator rep_iterator;
    t.erase((rep_iterator&)position); 
  }
  size_type erase(const key_type& x) { 
    return t.erase(x); 
  }
  void erase(iterator first, iterator last) { 
    typedef typename rep_type::iterator rep_iterator;
    t.erase((rep_iterator&)first, (rep_iterator&)last); 
  }
  void clear() { t.clear(); }

  // set operations:

  iterator find(const key_type& x) const { return t.find(x); }
  size_type count(const key_type& x) const { return t.count(x); }
  iterator lower_bound(const key_type& x) const {
    return t.lower_bound(x);
  }
  iterator upper_bound(const key_type& x) const {
    return t.upper_bound(x); 
  }
  pair<iterator,iterator> equal_range(const key_type& x) const {
    return t.equal_range(x);
  }
  friend bool operator== __STL_NULL_TMPL_ARGS (const set&, const set&);
  friend bool operator< __STL_NULL_TMPL_ARGS (const set&, const set&);
};

template <class Key, class Compare, class Alloc>
inline bool operator==(const set<Key, Compare, Alloc>& x, 
                       const set<Key, Compare, Alloc>& y) {
  return x.t == y.t;
}

template <class Key, class Compare, class Alloc>
inline bool operator<(const set<Key, Compare, Alloc>& x, 
                      const set<Key, Compare, Alloc>& y) {
  return x.t < y.t;
}

#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER

template <class Key, class Compare, class Alloc>
inline void swap(set<Key, Compare, Alloc>& x, 
                 set<Key, Compare, Alloc>& y) {
  x.swap(y);
}

#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma reset woff 1174
#endif

__STL_END_NAMESPACE

#endif /* __SGI_STL_INTERNAL_SET_H */

// Local Variables:
// mode:C++
// End:
  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值