欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STL源码剖析 5、关联式容器

程序员文章站 2024-02-11 20:52:04
...

关联式容器

STL源码剖析 5、关联式容器

树的导览

STL源码剖析 5、关联式容器
二叉搜索树
●任何节点的值一定大于左子树中每一个节点的值,并小于右子树的每一个节点的值。
●从根一直往左,直到无左路可走,就是最小元素(换成右就是最大)
●高度可能不平衡,造成搜索效率低,用AVL树改进
●中序遍历有序(刷题用)

AVL树:加了额外平衡条件的二叉搜索树
●任何节点的左右子树高度差最多为1
●违反平衡条件时用单旋转、双旋转 调整

红黑树 RB-tree

性质
●是二叉搜索树
●每个节点不是红色就是黑色
●根节点是黑色
●父子节点不能同时为红
●任意节点到叶子节点的路径所含黑节点数相同

各种算法:有点复杂,见书5.2
节点、迭代器、红黑树代码:见书

set

标准的STL set以RB-tree为底层机制,几乎所有的set操作行为都是转调用RB-tree的操作行为,如insert()、find()、count()

set的迭代器是const_iterator,无法写入
STL源码剖析 5、关联式容器

map

实现:map中以红黑树为底层机制,所有元素都为pair<const Key ,T>,pair的第一元素为键值(key),第二元素为实值(value)

template<class T1, class T2>
struct{
	typedef T1 first_type;
	typedef T2 second_type;
	T1 first;
	T2 second;
	pair() : first(T1()), second(T2()) {}	//不带参构造
	pair(const T1& a, const T2& b) : first(a), second(b) {}		//带参构造
}

只能修改second
STL源码剖析 5、关联式容器
operator[]

T& operator[](const key_type& k){
	return (*((insert(value_type(k,T()))).first)).second;
	//value_type(k,T())产生一个型别相同的临时对象(value_type是pair)
	//insert返回一个pair,第一元素是迭代器(重复就不插入,指向重复的),第二元素是插入成功与否
	//对first解引用获得存储的pair
	//对pair再去second获得value
}

●如果[]作为左值运用(添加新元素),正好返回要填的位置的引用
●如果[]作为右值(根据键取值),恰好返回旧键值对的值

multiset

和set的区别就是插入采用的是insert_equal()而不是insert_unique()

multimap

和map的区别就是插入采用的是insert_equal()而不是insert_unique()

hashtable

基本原理
 使用一个下标范围比较大的数组来存储元素。把关键字Key通过一个固定的算法函数即所谓的哈希函数(散列函数)转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标。
 为了避免哈希表太大,需要用到某种映射函数,将大数映射为小数,这种函数称为散列函数hash function。但hash function会带来碰撞问题,即不同的元素被映射到相同位置。

解决碰撞三种方法:
●线性探测:位置被占用了就往下一一寻找。插入多了后会浪费很多时候在解决碰撞上

●二次探测:位置被占用了就寻找i^2个,即H被使用的话寻找H+1,H+4,H+9…
 假设表格大小为质数,而且永远保持负载系数小于0.5(超过就重新配置),那么就可以确定没插入一个新元素所需要的探测次数不多于2

●开链法(hashtable使用):在每一个表格元素中维护一个list,list搜寻是线性操作,但是list够短的话速度还是很快
STL源码剖析 5、关联式容器
STL源码剖析 5、关联式容器

template<class Value>
struct _hashtable_node
{
	_hashtable_node *node;
	Value val;
};

hashtable存取过程
hash_map,首先分配一大片内存,形成许多桶。是利用hash函数,对key进行映射到不同区域(桶)进行保存。其插入过程是:

1.得到key
2.通过hash函数得到hash值(有些类型需要自定义hash函数)
3.得到桶号(一般都为hash值对桶数求模)
4.存放key和value在桶内。
其取值过程是:
1.得到key
2.通过hash函数得到hash值
3.得到桶号(一般都为hash值对桶数求模)
4.比较桶的内部元素是否与key相等,若都不相等,则没有找到。
5.取出相等的记录的value。

hashtable代码见书5.7

hash_set(即unordered_set)

set由红黑树实现,hash_set由hashtable实现
set的元素有自动排序功能而hash_set没有(hash_set效率更高)

hash_map(即unordered_map)

map由红黑树实现,hash_map由hashtable实现
map的元素有自动排序功能而hash_map没有(hash_map效率更高)

hash_multiset

hash_set的insert_equal()变为insert_unique(),允许插入重复值

hash_multimap

hash_map的insert_equal()变为insert_unique()

相关标签: STL源码剖析