STL关联容器概述

1. 概念

STL容器大的方向分为两类,序列式容器和关联式容器,这两者通过数据在容器内的排列来区分,关联容器是通过键(key)存储和读取元素的,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。
标准的STL序列容器包括:vector、list、deque、heap(算法呈现)、stack(适配器)、queue(适配器)、priority_queue(适配器)。标准的STL关联式容器包括:set、multiset、map、multimap。SGI STL还提供了一些非标准的关联式容器,eg:hash_table、hash_set。

2. 底层实现
先了解几个概念:
二叉搜索树是一种特殊的二叉树,其具有如下性质:
1) 若左子树不空,则左子树所有结点的值均小于它的根结点的值
2)若右子树不空,则右子树所有节点的值均大于它的根节点的值
3)左右子树也分别为二叉搜索树
二叉搜索树支持各种动态集合操作,包括:插入、查找、删除,其操作的时间复杂度与树的高度成正比,在遇到二叉树极端不平衡的情况下,其形状就与链表是一样的,二叉树插入、查找、删除的时间复杂度都退化为O(n)。
平衡二叉搜索树是一种特殊的二叉搜索树,其没有一个节点深度过大,不同的平衡条件,造就不同的效率表现。常见的平衡二叉搜索树有:AVL-tree和RB-tree。
关联容器一般以平衡二叉搜索树作为内部数据结构,RB-tree的应用尤其广泛。
RB-tree
是许多平衡二叉查找树的一种,一颗有n个内结点的红黑树的高度至多为2lg(n+1),
它能保证在最坏情况下,基本的动态集合操作时间为O(lgn)。

3. set / multiset
3.1 概念

set不区分键值和实值,其键值就是实值。顾名思义,可以把set当做集合使用,由于set的底层是平衡二叉搜索树,因此其在插入、查询和删除时都是O(lgn)的时间复杂度。set和multiset唯一的不同是,set不允许任何两个元素有相同的值,而multiset允许键值重复。

3.2 迭代器
set的迭代器本质上是const_iterator,这是因为RB-tree的结构依赖于数据的组织,如果允许通过iterator改变set元素值,会严重破坏RB-tree结构。此外,当对set进行插入和删除时,除了影响指向操作元素本身的迭代器之外,不影响指向其它元素的迭代器。

3.3 Set API
(constructor) Construct set (public member function)
(destructor) Set destructor (public member function)
operator= Copy container content (public member function)
Iterators:
begin Return iterator to beginning (public member function)
end Return iterator to end (public member function)
rbegin Return reverse iterator to reverse beginning (public member function)
rend Return reverse iterator to reverse end (public member function)
Capacity:
empty Test whether container is empty (public member function)
size Return container size (public member function)
max_size Return maximum size (public member function)
Modifiers:
insert Insert element (public member function)
erase Erase elements (public member function)
swap Swap content (public member function)
clear Clear content (public member function)
Observers:
key_comp Return comparison object (public member function)
value_comp Return comparison object (public member function)
Operations:
find Get iterator to element (public member function)
count Count elements with a specific key (public member function )
lower_bound Return iterator to lower bound (public member function)
upper_bound Return iterator to upper bound (public member function)
equal_range Get range of equal elements (public member function)
Allocator:
get_allocator Get allocator (public member function)

3.4 set实例:

#include <iostream>
#include <set>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
set<int> myset;
set<int>::iterator it, itlow, uplow;
int i;

// 插入数据
cout << "insert elements " << endl;
for (i=0; i<10; i++)
myset.insert(i*2);

int num = 4;

//查询、删除数据
cout << "find and delete element" << 4 << endl;
it=myset.find(num);
if(it != myset.end())
{
myset.erase(it);
}

num = 7;

// 元素边界
itlow = myset.lower_bound(num);
uplow = myset.upper_bound(num);
cout << num << " lower bound is " << *itlow << endl;
cout << num << " upper bound is " << *uplow << endl;
pair<set<int>::iterator,set<int>::iterator> ret = myset.equal_range(7);
cout << num << " lower bound is " << *ret.first << endl;
cout << num << " upper bound is " << *ret.second << endl;

// check数据是否在容器中
if (myset.count(num)>0)
cout << num << " is an element of myset.\n";
else
cout << num << " is not an element of myset.\n";

//输出容器大小
cout << "set size: " << (int) myset.size() << endl;

//输出容器内元素
cout << "myset contains:";
for (it=myset.begin(); it!=myset.end(); it++)
{
cout << " " << *it;
}
cout << endl;

system("pause");
return 0;
}

输出:
insert elements
find and delete element4
7 lower bound is 8
7 upper bound is 8
7 lower bound is 8
7 upper bound is 8
7 is not an element of myset.
set size: 9
myset contains: 0 2 6 8 10 12 14 16 18

4. map/ multimap
4.1 概念
和set相比,map同时拥有实值(value)和键值(key),其每一个元素都是pair,pair的第一个元素是键值,第二个元素是实值。map和multimap的区别在于,map不允许两个元素拥有相同的键值,而multimap允许存在重复的键值。
pair定义如下:

template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;

T1 first;
T2 second;
}

4.2 迭代器
map和set的底层实现都是很RB-tree,其迭代器特点和set一致。

4.3 Map API
(constructor) Construct map (public member function)
(destructor) Map destructor (public member function)
operator= Copy container content (public member function)
Iterators:
begin Return iterator to beginning (public member function)
end Return iterator to end (public member function)
rbegin Return reverse iterator to reverse beginning (public member function)
rend Return reverse iterator to reverse end (public member function)
Capacity:
empty Test whether container is empty (public member function)
size Return container size (public member function)
max_size Return maximum size (public member function)
Element access:
operator[] Access element (public member function)
Modifiers:
insert Insert element (public member function)
erase Erase elements (public member function)
swap Swap content (public member function)
clear Clear content (public member function)
Observers:
key_comp Return key comparison object (public member function)
value_comp Return value comparison object (public member function)
Operations:
find Get iterator to element (public member function )
count Count elements with a specific key (public member function)
lower_bound Return iterator to lower bound (public member function)
upper_bound Return iterator to upper bound (public member function)
equal_range Get range of equal elements (public member function)
Allocator:
get_allocator Get allocator (public member function)

4.4 map实例:
#include <iostream>
#include <map>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
map<char,int> mymap;
map<char,int>::iterator it;
pair<map<char,int>::iterator,bool> ret1;
pair<map<char,int>::iterator,map<char,int>::iterator> ret;

//插入元素
mymap['a']=10;
mymap['b']=20;
mymap['c']=30;
mymap['d']=40;
ret1=mymap.insert (pair<char,int>('c',500) );
if (ret1.second==false)
{
cout << "element 'c' already existed";
cout << " with a value of " << ret1.first->second << endl;
}

//寻找、删除
it=mymap.find('d');
mymap.erase (it);

//边界
ret = mymap.equal_range('b');
cout << "lower bound points to: ";
cout << ret.first->first << " => " << ret.first->second << endl;
cout << "upper bound points to: ";
cout << ret.second->first << " => " << ret.second->second << endl;

// 输出容器元素
cout << "mymap contains:\n";
for ( it=mymap.begin() ; it != mymap.end(); it++ )
cout << (*it).first << " => " << (*it).second << endl;

system("pause");
return 0;
}

输出:
element 'c' already existed with a value of 30
lower bound points to: b => 20
upper bound points to: c => 30
mymap contains:
a => 10
b => 20
c => 30

5. 结语
关联容器是把一个键值与一个元素联系起来,并使用该键来加速诸如查找、插入以及删除元素等操作。和序列容器相比,在使用键值来查找元素时,关联容器有更好的表现。

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值