#include <bits/stdc++.h>
using namespace std;
int j=12;
void puttt(std::vector<int> v2)
{
std::cout <<j<< ": ";
for(int i=0;i<v2.size();i++)
{
std::cout << v2[i] << " ";
}
std::cout <<std::endl;
std::cout <<std::endl;
std::cout <<std::endl;
std::cout <<std::endl;
j++;
}
int shi(int a)
{
return a<15;
}
int main()
{
int arr[]={1,2,3,4,5};
std::vector<int/*元素类型*/> v1(arr,arr+5);
//1.vector(begin,end)(两个指针)构造函数将前闭后开区间中元素拷贝给本身
std::vector<int >v2(5,10);
//2.vector(n,elem)将n个elem拷贝给本身
std::vector<int> v3(v1);
//拷贝构造函数
std::vector<int> v4;
std::vector<int> v5;
std::vector<int> v6;
v4.assign(v2.begin(),v2.end());
//将前闭后开的指针中间的值赋值给v2;end()函数指向末尾的下一位;
//也可以像v2一样赋值;
v5=v1;
//重载等号操作符;
v6=v2;
std::cout << "1: ";
//1
for(int i=0;i<5;i++)
{
std::cout << v1[i] << " ";
}
std:: cout << std::endl;
std::cout << "2: ";
//2
for(int i=0;i<5;i++)
{
std::cout << v2[i] << " ";
}
std::cout << std::endl;
std::cout << "3: ";
//3
for(int i=0;i<5;i++)
{
std::cout << v3[i] << " ";
}
std::cout << std::endl;
std::cout << "4: ";
//4
for(int i=0;i<5;i++)
{
std::cout << v4[i] << " ";
}
std::cout << std::endl;
std::cout << "5: ";
//5
for(int i=0;i<5;i++)
{
std::cout << v5[i] << " ";
}
std::cout << std::endl;
std::cout << "6: ";
//6
for(int i=0;i<5;i++)
{
std::cout << v6[i] << " ";
}
std::cout << std::endl;
v5.swap(v6);
//重载函数swap
//交换二者中元素 ;
std::cout << "7: ";
//7
for(int i=0;i<5;i++)
{
std::cout << v5 [i] << " ";
}
std::cout << std::endl;
std::cout << "8: ";
//8
for(int i=0;i<5;i++)
{
std::cout << v6[i] << " ";
}
std::cout << std::endl;
//size函数
int a=v1.size();
//返回元素的个数;
std::cout << a<<std::endl;
//empty函数
int b=v1.empty();
//判断容器是否为空(为空则返回一)
std::cout << b<<std::endl;
std::cout <<std::endl;
std::cout <<std::endl;
std::cout <<std::endl;
v2.resize(4);
//resize函数重载用法一:
//vector.resize(num);
//这个函数用于重新指定vector容器的长度为num。
//如果新的长度num大于当前容器的长度,那么容器会在末尾添加新的元素,这些新元素会被初始化为该类型的默认值。
//如果新的长度num小于当前容器的长度,那么容器会删除末尾超出新长度的元素。
std::cout << "9: ";
//9
for(int i=0;i<v2.size();i++)
{
std::cout << v2[i] << " ";
}
std::cout << std::endl;
std::cout <<std::endl;
std::cout <<std::endl;
std::cout <<std::endl;
v2.resize(9,100);
//resize函数重载用法二:
//vector.resize(num, elem);
//这个函数同样用于重新指定vector容器的长度为num。
//如果新的长度num大于当前容器的长度,那么容器会在末尾添加新的元素,这些新元素会被初始化为elem的值。
//如果新的长度num小于当前容器的长度,那么容器会删除末尾超出新长度的元素。
std::cout << "10: ";
//10
for(int i=0;i<v2.size();i++)
{
std::cout << v2[i] << " ";
}
std::cout <<std::endl;
std::cout <<std::endl;
std::cout <<std::endl; std::cout <<std::endl;
//v2.at(100)=5;//防止越界访问时程序终止不报错 ;
v2.push_back(1);
//push_back函数:
//在末尾插入一个元素;
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
v2.pop_back();
//pop_back函数:(无返回值)
//删除最末尾的元素
std::cout << "11: ";
//11
for(int i=0;i<v2.size();i++)
{
std::cout << v2[i] << " ";
}
std::cout <<std::endl;
std::cout <<std::endl;
v2.pop_back();
//***********************//
//insert函数: (多种重载用法)
//在指定位置插入一个元素;
v2.insert(v2.begin()+3,360);
//注意第一个参数为指针;在v2+3的位置插入一个元素,其他元素依次后移;(.begin取该容器的首地址)
//12
puttt(v2);
//在指定位置插入多个元素
v2.insert(v2.begin()+5,3,911);
//13
puttt(v2);
//将指定区间中多个元素插入到指定位置
v2.insert(v2.begin()+10,v1.begin()+2,v1.end());
//第一个参数是元素插入的首地址 ,第二个参数为插入元素的首地址,第三个为插入元素的末地址+1(数组直接取数组名)
//注意:指定区间为前闭后开
//14
puttt(v2);
//迭代器的使用
//构造一个迭代器对象
std::vector<int>::iterator it;
//it=v2.begin(); 让迭代器it指向v2的第一个元素
//15
std:: cout << "15: ";
for(it=v2.begin();it!=v2.end();it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
//迭代器的失效
it=v2.begin()+4;
v2.insert(it,1234);
std::cout << *it << std:: endl;
//16
std:: cout << "16: ";
for(it=v2.begin();it!=v2.end();it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
std::cout << *it << std:: endl; // 野指针
//失效原因:插入后是开辟一个新的空间来储存容器;但it还指向原来的地址;在dev中原数据不会被释放,所以输出原数据
//解决办法:运用insert的返回值(新的有效的迭代器);
//it=insert(it,123);//更新迭代器;
//erase函数(vector
//作用:两种重载形式,传入一个参数(地址),删除该地址所指向的元素;传入两个参数(地址),删除前闭后开区间内指向的元素
//返回值:函数返回一个迭代器。这个迭代器指向最后一个被删除元素之后的元素。
it=v2.begin()+4;
it=v2.erase(it,it+6);
std::cout << *it << std:: endl;
//17
std:: cout << "17: ";
for(it=v2.begin();it!=v2.end();it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
std::cout << *it << std:: endl;//野指针
//***********************************************************************************************//
//deque容器
//deque 是双端数组,而 vector 是单端的。
//deque 在接口上和 vector 非常相似,在许多操作的地方可以直接替换。
//deque 可以随机存取元素(支持索引值直接存取,用 [] 操作符或 at () 方法)。
//deque 头部和尾部添加或移除元素都非常快速,但是在中部安插元素或移除元素比较费时。
//适合在需要频繁在两端进行插入和删除操作的场景中使用,而 vector 更适合在尾部频繁操作以及在中间插入的场景
std::deque<int> d1={101,102,103,2,3,4};
std::deque<int>::iterator it2;
//18
std::cout<<"18: ";
for(it2=d1.begin();it2!=d1.end();it2++)
std::cout<< *it2 << " ";
std::cout<< std::endl;
std::cout<< std::endl;
std::cout<< std::endl;
d1.push_front(100);
//push_front函数
//相较与vector容器多出了对头部元素进行插入的函数
//19
std::cout<<"19: ";
for(it2=d1.begin();it2!=d1.end();it2++)
std::cout<< *it2 << " ";
std::cout<< std::endl;
std::cout<< std::endl;
std::cout<< std::endl;
d1.pop_front();
//pop_front函数
//相较与vector容器多出了对头部元素进行删除的函数
//20
std::cout<<"20: ";
for(int i:d1)
std::cout<< i << " ";
//这里使用了范围for循环来遍历myDeque容器中的元素。
//范围for循环的语法形式为for (元素类型 变量名 : 容器名),
//在每次循环时,会自动将容器中的下一个元素赋值给变量(这里是i),然后执行循环体中的代码。
std::cout<< std::endl;
std::cout<< std::endl;
std::cout<< std::endl;
//***********************************************************************************************//
//list容器
//list 是一个双向链表容器,可高效地进行插入和删除元素。(每个节点包含数据和指向前后节点的指针)
//list 不可以随机存取元素,所以不支持 at (pos) 函数与 [] 操作符。(储存空间非连续)
//不支持随机访问:由于list是链表结构,不支持通过索引直接访问元素。
//如果要访问list中的某个元素,通常需要从表头或表尾开始遍历,直到找到目标元素。
//在实际应用中,如果需要频繁随机访问元素,vector是更好的选择;
//如果需要频繁在中间进行插入和删除操作,list则更为合适。
/*在 C++ 编程中,list 容器适用于频繁进行插入和删除操作的场景,
但由于其不支持随机存取,在需要按索引访问元素的场景下不适用。(查找与更改的时间复杂度都为o(n)*/
/*例如,如果你需要在一个序列中频繁地在中间插入或删除元素,list 容器会比 vector 容器更高效,
因为 vector 在中间插入或删除元素可能会导致大量元素的移动.*/
std::list<int> l1={10,15,17,23,10,15};
l1.push_back(10);
l1.push_back(20);
std::list<int> l2(l1);
//21
std::cout<< "21: ";
for (int i : l1)
{
std::cout << i << " ";
}
std::cout << std::endl;
//操作一:
//元素存储:
//l.front()://返回第一个元素。不检查第一个元素是否存在。
//l.back()://返回最后一个元素。不检查最后一个元素是否存在。
//注意:与.begin(),.end()不同,一种返回的是元素本身;一种返回的是地址(.end()返回的是末地址的下一个地址)
//操作二:
//元素插入
//l.insert(pos,e)://在pos(指针)位置插入元素e的副本,并返回新元素位置。
//l.insert(pos,n,e)://在pos位置插入n个元素e的副本。
//l.insert(pos,begin,end)://在pos位置插入区间[begin,?end)内所有元素的副本。
//l.push_back(e)://在尾部添加一个元素e的副本。
//l.push_front(e)://在头部添加一个元素e的副本。
/*与vector相似,不给予演示*/
//操作三:
//元素的删除与更改
//**//l.pop_back()://移除最后一个元素。没有返回值。
//**//l.pop_front()://移除第一个元素。没有返回值。
//**//l.erase(pos)://删除pos位置的元素,返回下一个元素的位置。
//**//l.erase(begin,end)://删除区间[begin,end)内所有元素,返回下一个元素的位置。
/*与vector相似,不给予演示*/
//提示:erase的不当运用也会出现迭代器的失效,应当运用其返回值灵活解决;
//**//l.remove(val)://移除所有值为val的元素。
l1.remove(15);
//22
std::cout<< "22: ";
for (int i : l1)
{
std::cout << i << " ";
}
std::cout << std::endl;
//**//l.remove_if(op)://移除所有满足“op(val)==true”的元素。
l1.remove_if(shi);
//23
std::cout<< "23: ";
for (int i : l1)
{
std::cout << i << " ";
}
std::cout << std::endl;
//l.clear()://移除所有元素,清空容器。
//l.resize(num)://将元素数量改为num(增加的元素用默认构造函数产生,多余的元素被删除)。
//l.resize(num,e)://将元素数量改为num(增加的元素是e的副本)。
//其他操作
//l.unique()://移除重复元素。
l2.unique();
//24
std::cout<< "24: ";
for (int i : l2)
{
std::cout << i << " ";
}
std::cout << std::endl;
//l.unique(op)://移除满足“op(val)==true”的重复元素。
//list 特有函数splice
//std::list 容器提供了几个不同重载形式的 splice 函数,
//其主要功能是将一个 list 中的元素移动到另一个 list 的指定位置,这个操作是高效的,
//因为它只是调整链表节点的指针,不会涉及元素的复制或删除(除非有相关的析构等操作)。
//l1.splice(pos,l2)://将l2内的所有元素转移到l1的迭代器之前。
l1.splice(l1.end(), l2);
// 此时 list1 变为 {1, 2, 3, 4, 5, 6},list2 变为空
//25
std::cout<< "25: ";
for (int i : l1)
{
std::cout << i << " ";
}
std::cout << std::endl;
//l1.splice(pos,l2,l2pos)://将l2内l2pos所指元素转移到l1内的pos之前。
//注意:是转移到该位置之前
//l1.splice(pos,l2,l2begin,l2end)://将l2内[l2begin,l2end)区间内所有元素转移到l1的pos之前。
l2.splice(l2.end(),l1,l1.begin());
//26
std::cout<< "26: ";
for (int i : l2)
{
std::cout << i << " ";
}
std::cout << std::endl;
//l.sort()://以operator<为准则对所有元素排序。
//l.sort(op)://以op(定义“小于”关系)为准则对所有元素排序。
//l1.merge(l2)://假设l1和l2都已排序,将l2全部元素转移到l1并保证合并后仍是有序表。
//l.reverse()://将所有元素反序
//list的反向迭代器
//27
std::cout << "27: ";
list<int>::reverse_iterator it3;
for(it3=l1.rbegin();it3!=l1.rend();it3++)
{
std::cout << *it3 << " ";
}
std::cout << std::endl;
//rend()返回的也是首地址的前一位;
//提示:it++ 迭代器自增自减操作是可行的;it + 5 迭代器加一个整数操作是不可行的。
//***********************************************************************************************//
//stack容器
//stack(栈)是 C++ 标准模板库(STL)中的一种容器适配器。它遵循后进先出(LIFO - Last In First Out)的原则,
//就像一摞盘子,最后放上去的盘子最先被拿走。stack主要用于需要这种特殊访问顺序的场景,
//比如函数调用栈(在程序运行时,函数调用的顺序和返回顺序符合栈的特性)、表达式求值(如后缀表达式求值)等。
stack<int> st1;
st1.push(1);
st1.push(2);
st1.push(7);
st1.push(4);
st1.push(8);
st1.push(1);
st1.push(11);
cout << st1.top()<<endl;
//top返回栈顶元素,不会删除;
stack<int> st2(st1);//调用拷贝构造函数
stack<int> st3=st1;//调用拷贝构造函数
stack<int> st4;
st4=st1;//调用=重载
st1.pop();
//出栈,删除栈顶元素
cout << st1.top()<< " "<< st1.size()<<endl;
//stack容器 没有迭代器,不允许遍历;
//28
cout<< "28: ";
while(st1.empty()!=1)
{
cout<<st1.top()<< " ";
st1.pop();
} cout<< endl;
//***********************************************************************************************//
//queue容器
//queue(队列)是 C++ 标准模板库(STL)中的容器适配器
//它遵循先进先出(FIFO - First In First Out)的原则。可以把它想象成一个排队的队伍,先进入队伍的元素先离开。
//这种数据结构在很多场景中都非常有用,例如任务调度、广度优先搜索(BFS)算法等。
queue<int> q1;
q1.push(1);
q1.push(2);
q1.push(7);
q1.push(4);
q1.push(8);
q1.push(1);
q1.push(11);
cout << q1.front()<<endl;
//获取队头元素
cout << q1.back()<<endl;
//获取队尾元素
//拥有pop,size,empty的调用
//用法,函数都大致与stack相似,不一一赘述;
//***********************************************************************************************//
//set和multiset容器
//set存储的元素是唯一的并且按照特定的顺序(默认是升序)排列
//插入与删除更快
//所有存进去的元素都是有序的,不能指定插入位置;
//正向反向迭代器都有
/*set容器与multiset容器的区别在于set支持唯一键值,每个元素值只能出现一次
而multiset中同一值可以出现多出*/
//set容器不支持修改一个元素值,只能删除再插入;
set<int > s1;
//set<int,greater<int>>是按升序排列,默认为降序排列
//set<int,less<int>>是降序排列,等于set<int>
s1.insert(5);
s1.insert(2);
s1.insert(5);
s1.insert(8);
s1.insert(8);
s1.insert(0);
s1.insert(-4);
s1.insert(775);
set<int>::iterator it4;
//29
cout << "29: ";
for(it4=s1.begin();it4!=s1.end();it4++)
{
cout << *it4 << " ";
} cout <<endl;
set<int>:: reverse_iterator it5;
//30
cout << "30: ";
for(it5=s1.rbegin();it5!=s1.rend();it5++)
{
cout << *it5<< " ";
}cout << endl;
//find(elem)函数 ,查找elem,返回elem的迭代器
//31
cout << "31: ";
for(it4=s1.find(2);it4!=s1.end();it4++)
{
cout << *it4 << " ";
} cout << endl;
//count(elem)函数 返回elem的元素个数
//lower_bound(elem)函数 返回第一个>=elem元素的迭代器
//uper_bound(elem)函数 返回第一个<=elem元素的迭代器 (用于降序set)
//***********************************************************************************************//
//pair模板类
//pair是一个模板类,用于将两个不同类型的值组合成一个单一的对象
//pair提供了一种简单的方式来处理具有两个关联值的情况,比如在一个函数需要返回两个值,
//或者在容器(如map)中存储键 - 值对时非常有用。
pair<int,double> p1(10,0.1);
cout << p1.first << " : "<< p1.second <<endl;
//***********************************************************************************************//
//map容器
//map 存储的元素是键 - 值对,并且会根据键(key)自动进行排序
//存的是一对一对的对组
map<int,string > m1;
//map 的插入
//map.insert(pair<typ,typ>(key, value));或者map.insert({key, value});
m1.insert(pair<int,string>(1, "oo"));
//还可以直接构造一个pair p<int,int>(key,value); 插入p;
m1.insert({2, "tt"});
//map[key] = value;
//注意,使用 map[key] = value当map内存在一个相同的键值的时候,会覆盖掉这个键值
//而第一种方法不会;所以一般提倡使用第一种;(防止误伤)
m1[3]="th"; //([]的重载)
m1.insert(pair<int,string>(1, "ob"));
m1[3]="tw";
//map的迭代器的使用
map<int,string>::iterator it6;
for(it6=m1.begin();it6!=m1.end();it6++)
{
pair<int ,string> pr=*it6;
cout << pr.first << ": "<< pr.second<<endl;
}
//用键值对map中元素进行查找;
//find(elem)函数,返回第一个elem键值所对应的迭代器;
//如果找不到则返回find.end();
it6=m1.find(2);
pair<int ,string> pi=*it6;
cout << pi.first << ": "<< pi.second<<endl;
//使用map[i]进行访问(提示:如果不存在则创建一个键为i的键值对,默认值是" ";
//应当谨慎使用;
return 0;
}