C++ 之 STL

一、STL简介

是标准的模板库,将常见的数据结构以及算法进行封装。

特点:1.通用+灵活

           2.效率

二、六大部件

1.容器:

     1)vector(动态顺序表):底层维护了一端连续的空间

     2)string(字符的动态顺序表)

     3)list(双向循环链表) 

             list的迭代器不可以使用原生态指针。底层不是一段连续的空间。

            要将原生态的指针进行封装。因此需要将一些指针多具有的操作在类中进行重载。

   4)deque(双向开口的假想连续空间)

deque实则是维护一些分段定量的连续空间,将这些分段连续的空间管理好,造成其连续空间的假想,用户在使用时是一段连续的空间 

 

这是迭代器,缓冲区,中继器之间的相互关系。

  5)适配器

stack(先进后出)(尾插尾删)-->vector,但由于增容代价大,采用deque,增容效率高,不用拷贝,直接再给一段空间。

queue(先进先出)(头删尾插)-->list,用 deque ,不涉及遍历,用deque比较方便

priority——queue(堆) 默认为大堆

关联式容器:

一、里面存放的是具有关联关系的键值对<key,value>

键值实际是结构体:pair :first,second

二、二叉搜索树

1.左子树也是二叉搜索树,右子树也是二叉搜索树

2.左子树最左侧的为最小值,右子树最右侧为最大值。

3.中序是有序的

查找效率:log(N)

但是对于搜索二叉树来说,极端情况下会成为单支,退化成链表查找效率:O(N)

因此:底层并没有选择二叉搜索树,而是对此进行了优化。

三、AVL

搜索二叉树中每个结点的左右子树高度差(平衡因子)绝对值不超过1

平衡因子绝对值>1,就要进行旋转处理

插入过程:

1.按照二叉搜索树的规则插入新节点

2.更新平衡因子

四、红黑树

但是对于AVL,删除的时候可能要一直旋转到根,效率太低。因此采用一种近似平衡的二插搜索树---->红黑树

保证最长路径不超过最短路径的两倍。

性质:

1.每个结点不是红色就是黑色

2.根节点是黑色--->每次结点插入,就将根设为黑色

3.如果一个节点是红色,那么他的两个孩子都为黑色--->永远没有连在一起的红色

4.对于每一个接待,从该结点到其所有后代的简单路径上,均包含相同数目的

黑色结点个数---->默认插入颜色为红色-->可能违反性质3-->在调整

5.每个叶子结点都为黑色(空节点)--->为了保证第2点

插入过程:

1.按照二叉搜索树的规则插入新节点

2.检测数是否违反规则

为什么红黑树可以保证最长路径是最短路径的两倍

极端情况(不可能存在的),每两个黑色结点之间插入红色

五、底层为红黑树的关联式容器:

1.map(<key,value>):key必须唯一

2.multimap(<key,value>):key可以重复

3.set(值<key>但底层会构造<key,key>):key是唯一的:排序、去重

4.multiset:(值<key>但底层会构造<key,key>):key可以重复:排序

operator[]:底层用的insert实现的,为什么不用find?

是因为find去找。找到了返回数据,找不到就无法返回。

对于insert。insert(make.pair(x.T())).first.scond

1)若存在返回与之对应的值

2)不存在。insert就会构造一个默认的值,插入到红黑树中。返回这个默认值。若为内置类型,这个值可能为空。

也就是说用insert不管你要数据存不存在都会返回。

底层为哈希的关联式容器:无序

unorder_map

unorder_multimap

unorder_set

unorder_multiset

map和undered_map的区别?

1.map有序 undered_map无序

2.底层结构不一样 (1)红黑树(2)哈希桶

3.查找效率 (1)O(logn)   (2) O(1)

4.插入的方式:(1)按照搜索二叉树的规则插入新节点,在调整

                      (2)通过哈希函数计算桶号,插入节点 可能会产生哈希冲突

 5. 应用场景:(1)如果需要有序的关联式容器--->map

                         (2)  与是否有序无关--->查找效率高--->underedmap

6.空间利用率:O(N)--->map(用一个插一个)

                        underedmap-->如果哈希冲突-->概率较高-->徐散列-->增加桶的个数

7.迭代器

map--->双向的

 undered_map--->单向的--->单链表

迭代器什么时候会失效?

   指针指向的空间不能访问

每个容器负责给出相应的迭代器-->容器知道自己是哪种数据结构

vector:(1)如果有扩容的操作-->迭代器会失效--->需要重新赋值

                (resize,reserve,insert,push_back)

                 删除不会出错,空间不会释放,但会变得没有意义。(删的是最后一个。如果删的是中间,就会进行数据搬移,还是有意义的)

  list     (2)删除结点会失效,已经free了

                     插入不会

仿函数:又叫函数对象,一种行为类似函数的对象。调用者可以向函数一样使用用该对象。

实现:用户只需要实现一种新的类型,在类中进行重载(),参数根据用户索要进行的操作选择匹配

template<class T>
class Greater
{
public:
	bool operator()(const T& left,const T& right)
	{
		return left > right;
	}
};

template<class T,class Com>
void BubbleSort(T* array,size_t size,Com Compare)
{

	bool isChange = false;
	for (size_t i = 0; i < size - 1; ++i)
	{
		isChange = false;
		for (size_t j = 0; j < size - 1 - i; ++j)
		{
			if (Compare(array[j + 1], array[j])) //compare是对象,去调用了函数
			{
				swap(array[j], array[j + 1]);
				isChange = true;
			}
		}
		if (!isChange)
			return;
	}

}
void test()
{
	int array[] = { 2, 1, 5, 4, 6, 8, 9, 0, 3 };
	BubbleSort(array, 9, Greater<int>());
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值