【STL】关联式容器

来源:互联网 发布:程序员随身携带必备 编辑:程序博客网 时间:2024/05/18 02:55

【STL】常用容器总结,带有复习性质的学习更有效率;


【STL】 关联式容器复习

在复习关联式容器之前,先回忆一下底层的基本数据机构;

【树】: 常见的树有二叉树,搜索二叉树,RB_tree, AVL _tree, 哈弗曼树;

:下面只做特点的回顾,代码及具体细节有前面专门的博客,后面给出链接;

普通的二叉树即一种左右子树的结构,没有什么特别的地方,只是查找的时间复杂度为logn;

搜索二叉树的特点则是左子树的节点比中间节点的值小,右子树的节点的值比中间节点要大,关于搜索二叉树的面试题有一大堆,最后列出一些题作为巩固;

AVL_tree : 高度平衡二叉树,左右子树的高度差的绝对值不超过1;通过旋转达到平衡的目的,其中分为单旋转个双旋转,这是平衡二叉树的关键,面试的时候不会让你去写这个代码,但是旋转的过程一定要了解,曾经面去哪网的时候让我手画AVL树的旋转,恩,有些懵逼!

关于ALV树的面试题,有一道经典的题:判断一颗AVL树是否平衡;

RB_tree : 红黑树是在二叉搜索树节点的结构中加入了颜色属性,通过颜色的限制来平衡二叉树,达到尽量降低二叉树高度的目的;

关于红黑树的几个特点:1.根节点是黑节点2.没有连续的两个红色节点3.最长路径是最短路径的两倍4.所有叶子节点的孩子节点都是黑节点5.对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

下面是我以前写的关于红黑树比较详细的一篇文章:
红黑树

在STL中以红黑树作为底层容器有map, set, multiset, multimap; 但其实在C++标准库中 ,即C++11中加入了unordered_map,和unordered _set,set_symmetric_difference;

【set】 : 所有元素都会格局元素键值自动排序,set只有key值,其实因为底层是红黑树,底层是将value和key变为一样的; 同时set不允许有重复的key; set不允许通过迭代器改变key值,这样会破坏树的结构;

STL的set提供了相关算法,顺带一提,面cvte的时候,有一道编程题:求出2个字符串的差集;

我当时第一时间就想到了set, 愚蠢的是对set的接口的相关算法不熟悉了,导致伪代码都写得很挫;下面就以这道题为例子复习set;

set提供的相关算法:set_union(并集), set_difference(差集), set_intersection(交集)等;
#include <iostream>#include <set>#include <vector>#include <algorithm>using namespace std;int main(){    char arr1[] = "dasdfasf2";    char arr2[] = "dswdadss3";    set<char> s1(arr1, arr1+9);    set<char> s2(arr2, arr2+9);    vector<char> diff(10);    set_symmetric_difference(s1.begin(),s1.end(),s2.begin(), s2.end(),diff.begin());    for(int i = 0; i < diff.size(); ++i)    {        cout<<diff[i]<<" ";    }    cout<<endl;    system("pause");    return 0;}

set_symmetric_difference: 对称差集,即 (s1 - s2)U (s2 - s1); 这才是完整的两个字符串的差集;

当然,我当时采用的并不是这个算法,因为当时不知道有这个算法,于是只能自己造个轮子了;

#include <iostream>#include <set>#include <vector>using namespace std;int main(){    char* arr1 = "dasdfasf2";    char* arr2 = "dswdadss3";    set<char> s1(arr1, arr1+9);    set<char> s2(arr2, arr2+9);    vector<char> diff;    while ('\0' != *arr1 || '\0' != *arr2)    {        while('\0' != *arr1)        {            pair<set<char>::iterator, bool> ret = s2.insert(*arr1);            if(ret.second == true)            {                diff.push_back(*arr1);            }            ++arr1;        }        while('\0' != *arr2)        {            pair<set<char>::iterator, bool> ret = s1.insert(*arr2);            if(ret.second == true)            {                diff.push_back(*arr2);            }            ++arr2;        }    }    for(int i = 0; i < diff.size(); ++i)    {        cout<<diff[i]<<" ";    }    cout<<endl;    system("pause");    return 0;}

值得一提的是,set的insert返回的是一个pair类型的结构体,其中两个成员first 和 second;

【map】: map和set底层的数据结构都是红黑树,最大的不同之处就是map完整的采用了 key_value结构,可以通过map的迭代器来修改map的value值但是不可以修改key值,原因和set一样,会破坏树的结构;

map相比于set 还有一个新的特点就是重载了 ‘[ ]’; 可以通过[ ] 直接来查找或者插入新的元素;

比如说:

#include <iostream>#include <map>using namespace std;int main(){    map<char, int> m;    m['a'] = 1;    m['b'] = 2;    m['c'] = 3;    map<char, int>::iterator it = m.begin();    while(it != m.end())    {        cout<<it->first<<" : "<<it->second<<endl;        it++;    }    return 0;}

【multiset 和 multimap】:可重复key值的 set 和 map, 同样为了复用,使用的是同一颗红黑树结构,不同的是 set 和 map 在插入元素时调用的是 insert_unique, 而 multiset 和 multimap 调用的是 insert_equal;

二叉树常见面试题

原创粉丝点击