当前位置: 首页 > news >正文

快速入门C++第九天——STL库

Vector

Vector说明

  • vector是向量类型,可以容纳许多类型的数据,因此也被称为容器
  • 可以理解为动态数组,是封装好了的类
  • 进行vector操作前应添加头文件#include <vector>

vector初始化

方法一

//定义具有10个整型元素的向量(尖括号为元素类型名,它可以是任何合法的数据类型),不具有初值,其值不确定
vector<int>a(10);

方法二

//定义具有10个整型元素的向量,且给出的每个元素初值为1
vector<int>a(10,1);

方法三

//用向量b给向量a赋值,a的值完全等价于b的值
vector<int>a(b);

方法四

//将向量b中从0-2(共三个)的元素赋值给a,a的类型为int型
vector<int>a(b.begin(),b.begin+3);

方法五

 //从数组中获得初值
int b[7]={1,2,3,4,5,6,7};
vector<int> a(b,b+7);

vector对象的常用内置函数使用

#include<vector>
vector<int> a,b;
//b为向量,将b的0-2个元素赋值给向量a
a.assign(b.begin(),b.begin()+3);
//a含有4个值为2的元素
a.assign(4,2);
//返回a的最后一个元素
a.back();
//返回a的第一个元素
a.front();
//返回a的第i元素,当且仅当a存在
a[i];
//清空a中的元素
a.clear();
//判断a是否为空,空则返回true,非空则返回false
a.empty();
//删除a向量的最后一个元素
a.pop_back();
//删除a中第一个(从第0个算起)到第二个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)结束
a.erase(a.begin()+1,a.begin()+3);
//在a的最后一个向量后插入一个元素,其值为5
a.push_back(5);
//在a的第一个元素(从第0个算起)位置插入数值5,
a.insert(a.begin()+1,5);
//在a的第一个元素(从第0个算起)位置插入3个数,其值都为5
a.insert(a.begin()+1,3,5);
//b为数组,在a的第一个元素(从第0个元素算起)的位置插入b的第三个元素到第5个元素(不包括b+6)
a.insert(a.begin()+1,b+3,b+6);
//返回a中元素的个数
a.size();
//返回a在内存中总共可以容纳的元素个数
a.capacity();
//将a的现有元素个数调整至10个,多则删,少则补,其值随机
a.resize(10);
//将a的现有元素个数调整至10个,多则删,少则补,其值为2
a.resize(10,2);
//将a的容量扩充至100,
a.reserve(100);
//b为向量,将a中的元素和b中的元素整体交换
a.swap(b);
//b为向量,向量的比较操作还有 != >= > <= <
a==b;

顺序访问vector的几种方式

对向量a添加元素的几种方式

向向量a中添加元素

vector<int>a;
for(int i=0;i<10;++i){a.push_back(i);}

从数组中选择元素向向量中添加

int a[6]={1,2,3,4,5,6};
vector<int> b;
for(int i=0;i<=4;++i){b.push_back(a[i]);}

从现有向量中选择元素向向量中添加

int a[6]={1,2,3,4,5,6};
vector<int>b;
vector<int>c(a,a+4);
for(vector<int>::iterator it=c.begin();it<c.end();++it)
{
	b.push_back(*it);
}

从文件中读取元素向向量中添加

ifstream in("data.txt");
vector<int>a;
for(int i;in>>i){a.push_back(i);}

常见错误赋值方式

vector<int>a;
for(int i=0;i<10;++i){a[i]=i;}//下标只能用来获取已经存在的元素

从向量中读取元素

通过下标方式获取

int a[6]={1,2,3,4,5,6};
vector<int>b(a,a+4);
for(int i=0;i<=b.size()-1;++i){
    cout<<b[i]<<endl;
}

通过迭代器方式读取

int a[6]={1,2,3,4,5,6};
vector<int>b(a,a+4);
for(vector<int>::iterator it=b.begin();it!=b.end();it++){
    cout<<*it<<"  ";
}

几个常用的算法

#include<algorithm>
 //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列
sort(a.begin(),a.end());
 //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
reverse(a.begin(),a.end());
  //把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素
copy(a.begin(),a.end(),b.begin()+1);
 //在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置
find(a.begin(),a.end(),10);

List

简介

list 也是顺序容器的一种。只是list 是一个双向链表。使用 list 需要包含头文件 list。双向链表的每个元素中都有一个指针指向后一个元素,也有一个指针指向前一个元素,如下图所示。

当然,list的用法和vector很类似,也拥有顺序容器中的常用方法,需要注意的是list不支持使用下标随机存取元素

List的成员函数

void push_front(const T & val)                                  将 val 插入链表最前面

void pop_front()                                                        删除链表最前面的元素

void sort()                                                                 将链表从小到大排序

void remove (const T & val)                                     删除和 val 相等的元素


remove_if                                                                 删除符合某种条件的元素

void unique()                                                            删除所有和前一个元素相等的元素

void merge(list <T> & x)                                           将链表 x 合并进来并清空 x。要求链表自身和 x 都是有序的


void splice(iterator i, list <T> & x, iterator first, iterator last)            
在位置 i 前面插入链表 x 中的区间 [first, last),并在链表 x 中删除该区间。链表自身和链表 x 可以是同一个链表,只要 i 不在 [first, last) 中即可

list的用法实例

#include <iostream>
#include <list>

using namespace std;


int main(){

int a[6] = {1,3 ,2, 5,2,3};
int b[5] = {1,3,2,4,6};

list<int> L(a,a+6);
list<int> Lb(b,b+5);
list<int>::iterator pl;


cout<< "element in L : " ;
for(pl = L.begin(); pl != L.end();++pl){
    cout << *pl << " " ;
}
cout << endl;

cout<< "element in Lb : " ;
for(pl = Lb.begin(); pl != Lb.end();++pl){
    cout << *pl << " " ;
}
cout << endl;

L.sort();
cout<< "1) sort L: " ;

for(pl = L.begin(); pl != L.end();++pl){
    cout << *pl << " " ;
}
cout << endl;

cout <<"2) after delete element 2: ";
L.remove(2);
for(pl = L.begin(); pl != L.end();++pl){
    cout << *pl << " " ;
}
cout << endl;


cout << "3) delete first element in Lb: ";
Lb.pop_front();
for(pl = Lb.begin(); pl != Lb.end();++pl){
    cout << *pl << " " ;
}
cout << endl;

cout << "4) delete all same element in L: ";
L.unique();
for(pl = L.begin(); pl != L.end();++pl){
    cout << *pl << " " ;
}
cout << endl;

//使用merge
Lb.sort();
L.merge(Lb);
cout << "5) merge L with Lb: ";
L.unique();
for(pl = L.begin(); pl != L.end();++pl){
    cout << *pl << " " ;
}
cout << endl;
cout << "   size of Lb: " << Lb.size()<<endl;

L.reverse();
cout << "6) reverse L ";
 for(pl = L.begin(); pl != L.end();++pl){
    cout << *pl << " " ;
}
cout << endl;

return 0;
}

stack

stack简介

stack是一种先进先出的数据结构,被称为栈,它只有一端可以出入。
栈中进入数据称为——入栈(push)
栈中弹出数据称为——出栈(pop)

注意:

  • 栈可以判断是否为空,也可以返回栈中元素个数,但栈不允许有遍历行为
  • 使用stack容器必须包含头文件#include<stack>

stack的常用接口

构造函数

stack<T> stk; //stack采用模板类实现,默认构造,T为数据类型,如int等
stack(const stack &stk); //拷贝构造

赋值操作

stack& operator=(const stack& stk);//重载赋值运算符

数据存取

push(elem); //入栈,向栈顶添加元素
pop(); //出栈,删除栈顶元素
top(); //返回栈顶元素

大小操作

empty(); //判断栈是否为空
size(); //返回栈的大小

用法举例

void text()
{
	stack<int> stk1;
	for (int i = 0; i < 5; ++i)
	{
		stk1.push(i+10);
	}
	stack<int> stk2(stk1);
	cout << "stk1的大小为:" << stk1.size() << endl;
	cout << "stk2的大小为:" << stk2.size() << endl;
	//打印栈顶元素并出栈
	while (!stk1.empty())//栈非空时
	{
		cout << "stk1栈顶元素为:" << stk1.top() << endl;
		stk1.pop();
	}
	cout << "stk1的大小为:" << stk1.size() << endl;
	stk2 = stk1;
	cout << "stk2的大小为:" << stk2.size() << endl;
}

queue

queue的简介

queue是一种容器转换器模板,调用#include< queue>即可使用队列类。

queue<Type, Container> (<数据类型,容器类型>)

初始化时必须要有数据类型,容器可省略,省略时则默认为 deque 类型

queue<char, list<char>>q1;
//用list容器实现的queue 
 
queue<int, deque<int>>q2;
 //用deque容器实现的queue 

注意:不能用vector容器初始化queue
因为queue转换器要求容器支持front()、back()、push_back()及 pop_front(),说明queue的数据从容器后端入栈而从前端出栈。所以可以使用deque(double-ended queue,双端队列)和list对queue初始化,而vector因其缺少pop_front(),不能用于queue。

常用函数

  • push() 在队尾插入一个元素
  • pop() 删除队列第一个元素
  • size() 返回队列中元素个数
  • empty() 如果队列空则返回true
  • front() 返回队列中的第一个元素
  • back() 返回队列中最后一个元素

deque

deque简介

“deque” 是简写形式, 其原意为 “double-ended queue”。 deque 模板类提供了对序列随机访问的功能,可以实现在序列两端快速插入和删除操作 的功能, 在需要时修改自身大小。 deque 型容器是典型的双端队列, 可以完成标准C++ 数据 结构中队列的所有功能。

deque 是动态数组,在 STL 库的头文件 < deque >中

deque 型容器和 vector 型容器的对比:

  • deque 可以在两端迅速插入和删除元素, 而 vector 只提供了成员函数 push_back()和 pop_back()。
  • 存取元素时, deque 型容器会稍慢一些。
  • deque 型容器的迭代器是智能型指针。
  • 在内存区块受限制的系统中, deque 型容器可以包含更多元素, 因为它使用了多块 内存。
  • deque 型容器不支持对容器和内存重分配时机的控制。
  • deque 的内存区块不使用时, 会被释放。
  • 在序列中间插入和删除元素时, deque 的速度很慢, 需要移动相关的所有元素。
  • deque 型容器的迭代器属于随机存取迭代器。

deque 的定义和构造函数

无参,创建一个空双向队列

deque();

size - 创建一个大小为size的双向队列

deque( size_type size );

num and val - 放置num个val的拷贝到队列中

deque( size_type num, const TYPE &val );

from - 从from创建一个内容一样的双向队列

deque( const deque &from );

start 和 end - 创建一个队列,保存从start到end的元素

deque( input_iterator start, input_iterator end );

deque元素的存取和访问

pop_front()删除双向队列头部的元素

void pop_front();

pop_back()删除双向队列尾部的元素

void pop_back();

push_front()函数在双向队列的头部加入一个值为val的元素

void push_front( const TYPE &val );

push_back()函数在双向队列的尾部加入一个值为val的元素

void push_back( const TYPE &val );

顺序索引

  • 使用[]操作符访问双向队列中单个的元素
  • at()函数返回一个引用,指向双向队列中位置pos上的元素
reference at( size_type pos );

元素引用

  • front()函数返回一个引用,指向双向队列的头部
  • back()返回一个引用,指向双向队列中最后一个元素

迭代器相关

  • begin()函数返回一个迭代器,指向双向队列的第一个元素
  • end()函数返回一个迭代器,指向双向队列的尾部
  • rbegin()返回一个指向双向队列尾部的逆向迭代器
  • rend()返回一个指向双向队列头部的逆向迭代器

deque容器的容量

  • empty()返回真如果双向队列为空,否则返回假
  • size()函数返回双向队列中的元素个数
  • resize()改变双向队列的大小为num,另加入的元素都被填充为val

deque基本操作

队列赋值

  • assign()函数用start和end指示的范围为双向队列赋值
void assign( input_iterator start, input_iterator end);
  • assign()函数设置成num个val
void assign( Size num, const TYPE &val );

清空队列

  • clear()函数删除双向队列中所有元素

删除元素

  • erase()函数删除pos位置上的元素,返回值是一个iterator,指向被删除元素的后一个元素
iterator erase( iterator pos );
  • erase()函数删除start和end之间的所有元素,返回值是一个iterator,指向被删除元素的后一个元素
iterator erase( iterator start, iterator end );

插入元素

  • insert()在pos前插入num个val值,该函数返回一个迭代器,该迭代器指向新插入的元素中的第一个
iterator insert( iterator pos, size_type num, const TYPE &val );
  • insert()插入从start到end范围内的元素到pos前面
void insert( iterator pos, input_iterator start, input_iterator end );

交换队列

  • swap()函数交换target和现双向队列中元素
void swap( deque &target );

set

set的简介

set就是集合,STL的set用二叉树实现,集合中的每个元素只出现一次(参照数学中集合的互斥性),并且是排好序的(默认按键值升序排列)

常用操作

set<int> q;     //以int型为例 默认按键值升序
set<int,greater<int>> p;  //降序排列 
int x;
q.insert(x);	//将x插入q中
q.erase(x);		//删除q中的x元素,返回0或1,0表示set中不存在x
q.clear();		//清空q
q.empty();		//判断q是否为空,若是返回1,否则返回0
q.size();		//返回q中元素的个数
q.find(x);		//在q中查找x,返回x的迭代器,若x不存在,则返回指向q尾部的迭代器即 q.end()
q.lower_bound(x); //返回一个迭代器,指向第一个键值不小于x的元素
q.upper_bound(x); //返回一个迭代器,指向第一个键值大于x的元素

q.rend();		  //返回第一个元素的的前一个元素迭代器
q.begin();		  //返回指向q中第一个元素的迭代器

q.end();		 //返回指向q最后一个元素下一个位置的迭代器
q.rbegin();		 //返回最后一个元素

map

map简介

map是STL的一个关联容器,以键值对存储的数据,其类型可以自己定义,每个关键字在map中只能出现一次,关键字不能修改,值可以修改;map同set、multiset、multimap(与map的差别仅在于multimap允许一个键对应多个值)内部数据结构都是红黑树,而java中的hashmap是以hash table实现的。

map<string,int> my_map;
也可以使用
typedef map<string,int> My_Map;
My_Map my_map;

常用方法

函数名功能
my_map.insert()或按照数组直接赋值 插入
my_map.find()擦查找一个元素
my_map.clear()清空
my_map.erase()删除一个元素
my_map.size()map的长度大小
my_map.begin()返回指向map头部的迭代器
my_map.end()返回指向map末尾的迭代器
my_map.rbegin()返回一个指向map尾部的逆向迭代器
my_map.rend()返回一个指向map头部的逆向迭代器
my_map.empty()map为空时返回true
swap()交换两个map,两个map中所有元素都交换

map插入数据的几种方法

第一种:用insert函数插入pair数据:
map<int,string> my_map;
my_map.insert(pair<int,string>(1,"first"));
my_map.insert(pair<int,string>(2,"second"));
第二种:用insert函数插入value_type数据:
map<int,string> my_map;
my_map.insert(map<int,string>::value_type(1,"first"));
my_map.insert(map<int,string>::value_type(2,"second"));
 
map<int,string>::iterator it;           //迭代器遍历
for(it=my_map.begin();it!=my_map.end();it++)
    cout<<it->first<<it->second<<endl;
第三种:用数组的方式直接赋值:
map<int,string> my_map;
my_map[1]="first";
my_map[2]="second";
 
map<int,string>::iterator it;
for(it=my_map.begin();it!=my_map.end();it++)
    cout<<it->first<<it->second<<endl;

查找元素(判定这个关键字是否在map中出现)

第一种:用count函数来判断关键字是否出现,其缺点是无法定位元素出现的位置。由于map一对一的映射关系,count函数的返回值要么是0,要么是1。

map<string,int> my_map;
my_map["first"]=1;
cout<<my_map.count("first")<<endl;    //输出1;

第二种:用find函数来定位元素出现的位置,它返回一个迭代器,当数据出现时,返回的是数据所在位置的迭代器;若map中没有要查找的数据,返回的迭代器等于end函数返回的迭代器。

#include <map>  
#include <string>  
#include <iostream>  
 
using namespace std;  
  
int main()  
{  
    map<int, string> my_map;  
    my_map.insert(pair<int, string>(1, "student_one"));  
    my_map.insert(pair<int, string>(2, "student_two"));  
    my_map.insert(pair<int, string>(3, "student_three"));  
    map<int, string>::iterator it;  
    it = my_map.find(1);  
    if(it != my_map.end())  
       cout<<"Find, the value is "<<it->second<<endl;      
    else  
       cout<<"Do not Find"<<endl;  
    return 0;  
}
//通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据iterator->first和iterator->second,分别代表关键字和value值。

删除元素

#include <map>  
#include <string>  
#include <iostream>  
  
using namespace std;  
  
int main()  
{  
    map<int, string> my_map;  
    my_map.insert(pair<int, string>(1, "one"));  
    my_map.insert(pair<int, string>(2, "two"));  
    my_map.insert(pair<int, string>(3, "three"));  
    //如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好
    //如果要删除1,用迭代器删除
    map<int, string>::iterator it;  
    it = my_map.find(1);  
    my_map.erase(it);                   //如果要删除1,用关键字删除
    int n = my_map.erase(1);            //如果删除了会返回1,否则返回0
    //用迭代器,成片的删除
    //一下代码把整个map清空
    my_map.erase( my_map.begin(), my_map.end() );  
    //成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合
    //自个加上遍历代码,打印输出吧
    return 0;
}  

排序,按value排序

map中元素是自动按key升序排序(从小到大)的;按照value排序时,想直接使用sort函数是做不到的,sort函数只支持数组、vector、list、queue等的排序,无法对map排序,那么就需要把map放在vector中,再对vector进行排序。

#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
 
bool cmp(pair<string,int> a, pair<string,int> b) {
	return a.second < b.second;
}
 
int main()
{
    map<string, int> ma;
    ma["Alice"] = 86;
    ma["Bob"] = 78;
    ma["Zip"] = 92;
    ma["Stdevn"] = 88;
    vector< pair<string,int> > vec(ma.begin(),ma.end());
    //或者:
    //vector< pair<string,int> > vec;
    //for(map<string,int>::iterator it = ma.begin(); it != ma.end(); it++)
    //    vec.push_back( pair<string,int>(it->first,it->second) );
 
    sort(vec.begin(),vec.end(),cmp);
    for (vector< pair<string,int> >::iterator it = vec.begin(); it != vec.end(); ++it)
    {
        cout << it->first << " " << it->second << endl;
    }
    return 0;
}
espace std;
 
bool cmp(pair<string,int> a, pair<string,int> b) {
	return a.second < b.second;
}
 
int main()
{
    map<string, int> ma;
    ma["Alice"] = 86;
    ma["Bob"] = 78;
    ma["Zip"] = 92;
    ma["Stdevn"] = 88;
    vector< pair<string,int> > vec(ma.begin(),ma.end());
    //或者:
    //vector< pair<string,int> > vec;
    //for(map<string,int>::iterator it = ma.begin(); it != ma.end(); it++)
    //    vec.push_back( pair<string,int>(it->first,it->second) );
 
    sort(vec.begin(),vec.end(),cmp);
    for (vector< pair<string,int> >::iterator it = vec.begin(); it != vec.end(); ++it)
    {
        cout << it->first << " " << it->second << endl;
    }
    return 0;
}

相关文章:

  • 深度神经网络是什么意思,深度神经网络通俗理解
  • 快速入门C++第八天——异常处理和命名空间
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • OPENSSH PRIVATE 转换 RSA PRIVATE 以及区别
  • 计算机毕业设计ssm体育赛事信息平台dmlva系统+程序+源码+lw+远程部署
  • 网课查题公众号接口调用详细教程
  • 计算机毕业设计ssm通识教育教学系统ekzep系统+程序+源码+lw+远程部署
  • 网课查题接口对接教程
  • 网课答案搜题接口对接教程
  • 计算机毕业设计ssm桐梓娄山书店管理系统6k3s6系统+程序+源码+lw+远程部署
  • c c++源文件依赖关系分析工具
  • yolo系列之yolov4(4)
  • JavaFX、聊天程序
  • SVO2.0
  • WebWall-09.Unsafe file uploads(不安全的文件上传)
  • (三)从jvm层面了解线程的启动和停止
  • 2017前端实习生面试总结
  • 4个实用的微服务测试策略
  • CentOS6 编译安装 redis-3.2.3
  • Leetcode 27 Remove Element
  • PAT A1050
  • spring-boot List转Page
  • Vue.js 移动端适配之 vw 解决方案
  • 笨办法学C 练习34:动态数组
  • 复习Javascript专题(四):js中的深浅拷贝
  • 给新手的新浪微博 SDK 集成教程【一】
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 缓存与缓冲
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 实现菜单下拉伸展折叠效果demo
  • 微信开放平台全网发布【失败】的几点排查方法
  • 小而合理的前端理论:rscss和rsjs
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​2020 年大前端技术趋势解读
  • # include “ “ 和 # include < >两者的区别
  • # 达梦数据库知识点
  • #Z2294. 打印树的直径
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (附源码)ssm高校实验室 毕业设计 800008
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (已解决)什么是vue导航守卫
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)setTimeout 和 setInterval 的区别
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .mysql secret在哪_MySQL如何使用索引
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .net反混淆脱壳工具de4dot的使用
  • .Net接口调试与案例