STL容器大总结区分(上)

STL容器大总结区分(上)_第1张图片

如图所示 ,按大小说明其重要性

那就先说两个最重要的:

vector---数组              list-----链表

vector 基本概念
功能:
vector 数据结构和 数组非常 相似 ,也称为 单端数组
vector 与普通数组区别:
不同之处在于数组是静态空间,而 vector 可以 动态扩展
动态扩展:
并不是在原空间之后续接新空间,而是找更大的内存空间 ,然后将原数据 拷贝 新空间,释放原空间
vector 容器的迭代器是支持 随机访问 的迭代器

list 链表  
有数据域和指针域
优点 1可以对任意位置进行快速插入和删除元素    2动态分配存储 
缺点 容器遍历速度慢,因为要通过指针域来找元素,比数组慢。占用的空间也比数组大,因为有数据域和指针域。
STL中的链表是一个双向循环链表
支持头部和尾部的插入删除 
链表的存储方式不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器 


list有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的
因为,vector如果满了,就会开辟新内存空间,原有迭代器会失效 
可以想象vector是一排连接起来的箱子,list是独立的箱子,放哪都不会影响内存

说到这,插入一个知识点
STL容器大总结区分(上)_第2张图片
vector                                                 随机访问迭代器
deque                                                 随机访问迭代器
list                                                     双向迭代器
set/multiset                                                     双向迭代器
map/multimap                                                       双向迭代器
stack                                                 不支持迭代器
queue                                                         不支持

好,言归正传

先从构造函数开始讲,这几类的方式都大差不差,包括构造时候和赋值和删除插入时

先从构造时候说

在list和vector都有四种方式构造函数

默认构造 无参构造 

还可通过区间的方式进行构造

n个elem方式构造

拷贝构造

实例说明

vector的

void test01(){
	vector v1;//默认构造 无参构造     
	for(int i=0;i<=10;i++){
		v1.push_back(i);
	} 						//掌握好第一个和第四个  构造完后面赋值就好 
	printVector(v1);
	
	//还可通过区间的方式进行构造
	vector v2(v1.begin(),v1.end()) ;
	printVector(v2);
	
	//n个elem方式构造
	vector v3(10,100);//十个100 
	printVector(v3);
	
	//拷贝构造
	vector v4(v3);
	printVector(v4); 
}

list的

void test01(){
	list l1;
	//添加数据 
	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);
	l1.push_back(40);
	//遍历容器
	printList(l1); 
	//区间方式构造
	listL2(l1.begin(),l1.end());
	printList(L2); 
	//拷贝构造
	listL3(L2);
	printList(L3);
	//n个elem
	listl4(10,1000);
	printList(l4); 
} 

不一样的只是容器名,其他几个也大差不差,一会也一并说了其相似和差异

继续说  赋值方式   两个一样,都是四种

默认赋值

赋值    operator=

assign

assign    n个elem方式赋值

//vector赋值
void test01(){
	vector v1;//默认赋值 
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	printVector(v1);
	
	//赋值	operator=
	vector v2; 
	v2=v1;
	printVector(v2);
	
	//assign
	vector v3;
	v3.assign(v1.begin(),v1.end());
	printVector(v3);
	
	//assign	n个elem方式赋值
	vector v4;
	v4.assign(10,100);
	printVector(v4); 
	
} 

list赋值

void test01(){
	listL1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	
	printList(L1);
	
	listL2;
	L2=L1;//operator=赋值
	printList(L2);
	
	listL3;
	L3.assign(L2.begin(),L2.end()) ;
	printList(L3);
	
	listL4;
	L4.assign(10,100);
	printList(L4);
} 

vector和list容器(只有vec)大小

vector和list大小操作

这几个接口

empty size capacity resize

capacity        list么有

vector

void test01(){
	vector v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	printVector(v1);
	
	if(v1.empty())//为真 为空
	{
		cout<<"v1为空"<

list

void test01(){
	listL1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	
	printList(L1);
	
	if(L1.empty()){
		cout<<"L1为空"<

插入和删除

尾删和尾插两个都有        因为在随机访问迭代器中在头部上处理的是下一个容器deque,这里暂且不表   要分清front和x.begin()所表示什么

尾插    v1.push_back(40);     L.push_back(10);

尾删  v1.pop_back();                    L.pop_back();

insert一样

vector

	//插入	第一个参数是 迭代器 
	v1.insert(v1.begin(),100);
	printVector(v1); 
	
	v1.insert(v1.end(),200);
	printVector(v1);
	
	v1.insert(v1.begin(),2,1000);
	printVector(v1);//加了两个1000

list

//insert插入
	list::iterator it=L.begin();
	L.insert(++L.begin(),1000);//it灵活运用 
	printList(L);
	L.insert(L.end(),2,9);
	printList(L);

接下来说删除,删除这稍微不一样

通常就是erase()和clear()   list加了一个remove()

	//删除	参数也是 迭代器 
	v1.erase(v1.begin()) ;
	printVector(v1);
	
//	v1.erase(v1.begin(),v1.end());//清除区间		删除第三个2到4 
	v1.clear() ;//也是清除区间 
	printVector(v1);

list

	//删除
	it=L.begin();
	L.erase(it);
	printList(L);//删了200
	
	//移除
	L.push_back(10000);
	L.push_back(10000);
	L.push_back(10000);
	printList(L);
	
	L.remove(10000);//删除所有匹配的值 
	printList(L);//删掉了 
	
	
	//清空
	L.clear();
	printList(L);//多了一个空行 

    L.remove(10000);//删除所有匹配的值 
    printList(L);//删掉了 

删除的是所有remove里面的数(1000)

数据存储

vector可以用[]和at()访问        和获取第一个元素v1.front()    获取最后一个v1.back()

void test01(){
	vector v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	//利用中括号方式来访问数组中的元素 
	for(int i=0;i

list不支持at()和[],因为链表不是连续空间    而且链表也不支持随机访问,双向迭代器只能前移和后移              这句说的太好了           防止忘记,让我们再次回顾list优点缺点

优点 1可以对任意位置进行快速插入和删除元素    2动态分配存储 
缺点 容器遍历速度慢,因为要通过指针域来找元素,比数组慢。占用的空间也比数组大,因为有数据域和指针域。

void test01(){
	listL1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	
//	L1[0]是错误的L.at(0)错误
	
	cout<<"第一个元素为"<::iterator it=L1.begin();
	it++;//正确	支持双向
	it--; 
//	it+=1;报错  其不支持随机访问  可以用加法来判断是否支持随机访问
//或者写it--看其是否为单向 
	cout<<*it; 
	
} 

这一段着重看,学思想  

 //验证迭代器是不支持随机访问的
    list::iterator it=L1.begin();
    it++;//正确    支持双向
    it--; 
//    it+=1;报错  其不支持随机访问  可以用加法来判断是否支持随机访问
//或者写it--看其是否为单向 
    cout<<*it;

  swap()

两个都有swap()属性,但这里list用reverse来表示
vector

void test01(){
	vector v1;
	for(int i=0;i<10;i++){
		v1.push_back(i);
	}
	cout<<"交换前"< v2;
	for(int i=10;i>0;i--){
		v2.push_back(i);
	}
	printVector(v2);
	
	cout<<"交换后"<

vector        swap()实际用途

//巧用swap()可以收缩内存空间
void test02(){
	vector v;
	for(int i=0;i<100000;i++){
		v.push_back(i);
	}
	cout<<"v的容量为:"<(v).swap(v);
	cout<<"v的容量为:"<(v) 其内存和大小都是3 
	//然后swap 指针方向交换 所以v内存和大小都为3
	//匿名对象指向的大空间 当前行执行完立即回收,所以不存在占空间 
} 

 

list

void test01(){
	//反转 
	listL1;
	
	L1.push_back(20);
	L1.push_back(10);
	L1.push_back(50);
	L1.push_back(40);
	L1.push_back(30);
	
	printList(L1);
	
	cout<<"反转后"<

 

接下来是两个独有属性

 list排序

//排序
void test02(){
	listL1;
	L1.push_back(20);
	L1.push_back(10);
	L1.push_back(50);
	L1.push_back(40);
	L1.push_back(30);
	cout<<"排序前"<

重点是

    sort(L1.begin(),L1.end());报错
     原因所有不支持随机访问迭代器的容器,不可以用标准算法
     不支持随机访问的迭代器,内部会提供对应的一些算法

所以    L1.sort();//运行成功     默认从小到大 

vector预留空间

统计开辟内存次数                        用reserve先开辟内存就不用后面再开辟了

#include 
#include 
#include
using namespace std;
//reserve(int len)//容器预留len个元素长度,预留位置不初始化,元素不可访问

void test01(){
	vector v;
	
	//利用reserve预留空间
	v.reserve(100000); //这回运行结果为0 
	int num=0;//统计开辟内存次数
	int*p=NULL; 
	for(int i=0;i<100000;i++){
		v.push_back(i);
		if(p!=&v[0]){
			p=&v[0];//循环找第一个内存  
			num++;
		}
	}	
	//vector可动态拓展 是找一块更大的空间 把原有的数据拷贝新空间,释放原空间
	cout<

两个print函数

void printVector(vector &v){
    for(vector::iterator it=v.begin();it!=v.end();it++){
        cout<<*it<<" ";
    }
    cout< }

如此看来两个除了容器名不同,输出其他都相同

void printList(list &L){
    for(list::iterator it=L.begin();it!=L.end();it++){
        cout<<*it<<" ";
    }
    cout< }

你可能感兴趣的:(50,c++,开发语言,数据结构,算法)