vector与deque的迭代器支持算术运算,list的迭代器只能进行++/–操作,不支持普通的算术运算。
引用头文件
vector<int> pos(32, -1);//定义32个字符
vector<char> a(32);
a.pop_back();
a.push_back(0);
首先这是动态的,非常灵活。储存的时候是连续的线性空间,支持高效的随机访问和在尾端插入/删除操作,但其他位置的插入/删除操作效率低下。
class Vector
{
public:
iterator start;
iterator begin(){return start};
//目前使用了的空间头
iterator finish;
iterator end(){return finish};
//目前使用了的空间的尾
size_type size(){ return size_type(end-start);}
reference front() {return *begin();}
reference back(){return *(end()-1);}
iterator end_of_storage; //目前可用空间的尾
bool empty(){return begin()==end();}
}
当我们用push_back插入的时候,会检查 还有没有备用的空间 ,如果没有的话
要经历allocator先按规则分配空间 然后把之前的拷贝过去, 再插入,最后释放原来的空间 这是一个庞大的工程
分配空间的规则
{
如果原本大小为0
分配空间为1;
else
分配空间为=原来的*2;
}
引用头文件
我们知道连续内存的容器不能随意扩充,因为这样容易扩充别人那去。deque却可以,它创造了内存连续的假象。其实deque由一段一段构成 ,他是分段连续,而不是内存连续 当走向段的尾端时候自动跳到下一段 所以支持迭代器++ 操作,自动跳到下一段的方法由operator++实现。deque每次扩充 则申请一个段,双端队列底层是一段假象的连续空间,实际是分段连续的,“整体连续”的假象。可以头插和尾插,也可以弹出队首和队尾。
b.push_front(0);
b.push_front(0);
b.pop_back();
b.pop_front();
如果只是简单的存储元素使用vector就可以了,如果对元素任意位置进行插入或者删除操作比较多,则使用list即可,所以一般很少使用deque;deque的最大应用,就是用其作为标准库中stack和queue的底层结构。
引用头文件,list底层是一个带头节点的双向循环链表,任意位置插入和删除时间复杂度0(1)。
引用
引用
引用
模版原型:priority_queue<T,Sequence,Compare>
priority_queue<int, vector<int>, greater<int>> c;
实现优先级队列的底层容器,默认是vector;
第三个参数是c++比较函数。默认情况下是less;
集合(set)是一种包含已排序对象的关联容器,不允许有重复元素。无序集合(unordered_set)则元素不重复且无序。set(
红黑树:
优点:很多操作在lg(n)的时间复杂度下就可以实现,因此效率非常的高
缺点: 空间占用率高,因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
红黑树,Red-Black Tree 「RBT」是一个自平衡(不是绝对的平衡)的二叉查找树(BST),树上的每个节点都遵循下面的规则:
性质1:每个节点要么是黑色,要么是红色。
性质2:根节点是黑色。
性质3:每个叶子节点(NIL)是黑色。
性质4:每个红色结点的两个子结点一定都是黑色,没有两个相邻的红色节点(并没有说不能出现连续的黑色节点)
性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。
平衡二叉树
平衡二叉树,又称AVL树,指的是左子树上的所有节点的值都比根节点的值小,而右子树上的所有节点的值都比根节点的值大,且左子树与右子树的高度差最大为1。因此,平衡二叉树满足所有二叉排序(搜索)树的性质。插入和删除节点需要重新平衡,主要有四种调整方式:LL(左旋)、RR(右旋)、LR(先左旋再右旋)、RL(先右旋再左旋)。
哈希表:
优点:查找速度非常的快
缺点: 哈希表的建立比较耗费时间
哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
不管hash函数设计的如何巧妙,总会有特殊的key导致hash冲突,特别是对动态查找表来说。
hash函数解决冲突的方法有以下几个常用的方法
1.开放定制法
2.链地址法
3.公共溢出区法
建立一个特殊存储空间,专门存放冲突的数据。此种方法适用于数据和冲突较少的情况。
4.再散列法
准备若干个hash函数,如果使用第一个hash函数发生了冲突,就使用第二个hash函数…
typedef struct {
char* Key;
char* Value;
hash_node* next;
}hash_node;//节点
typedef struct {
int size;
int count;
hash_node* node;
}hash_table;//表
map(
map、set、multiset、multimap这四种关联容器是有序的。有序的含义是它们按照顺序进行存储。
std::pair主要的作用是将两个数据组合成一个数据,两个数据可以是同一类型或者不同类型。pair是将2个数据组合成一个数据,例如stl中的map就是将key,value放在一起来保存。当一个函数需要返回2个数据的时候,可以选择pair。 pair的实现是一个结构体,主要的两个成员变量是first,second 因为是使用struct不是class,所以可以直接使用pair的成员变量。
template pair make_pair(T1 a, T2 b)
{
return pair(a, b);
}
我们可以使用pair的构造函数也可以使用make_pair来生成我们需要的pair。 一般make_pair都使用在需要pair做参数的位置,可以直接调用make_pair生成pair对象。
vector<pair<int, int>> p(10,make_pair<int, int>(45, 99));
cout << p[0].first << endl;//first得到pair的第一个值
cout << p[9].second << endl;//second得到第二个值
C++ 标准模板库 STL(Standard Template Library) 一共给我们提供了四种智能指针:(
实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄露。
实现共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。可以通过成员函数use_count()来查看资源的所有者个数。除了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放。shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的), 在使用引用计数的机制上提供了可以共享所有权的智能指针。
一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引用的 shared_ptr. weak_ptr只是提供了对管理对象的一个访问手段。weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。