【C++】标准模板库(上)


C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈。

vector封装数组,list封装了链表,map和set封装了二叉树等

一、vector

vector是一种「变长数组」,即“自动改变数组长度的数组”。

vector可以用来以邻接表的方式储存图,非常友好,非常简洁。

2.定义

可以像定义变量一样来定义一个vector类型的数组。

vector<int> a;

其中尖括号中的类型可以换成其他的任何类型,也可以换成一个vector<int>的类型,这时,就相当于定义了一个二维的数组,其元素的个数是可变的,并且其元素的元素的个数也是可变的。

vector<vector<int> > b;

注意:vector<vector > b; >>之间要加空格。

还有另外一种二维数组的定义方法

vector<int> c[100];

这种定义在算法中经常会用到,因为题目上大概率会把第一维的最大值给定。

3.元素访问

vector一般有两种访问方式,第一种最直接也最常用:

1.通过下标访问
这个和数组相似,可以直接使用a[i][j]进行访问。

2.通过迭代器访问
迭代器(iterator)可以理解为指针:
在使用之前要先定义一个迭代器:

vector<类型名>::iterator 变量名;

举个例子:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    //v.begin()返回v的首元素地址
    vector<int>::iterator it=v.begin();
    for (int i = 0; i < v.size(); i++)
    {
       cout<<it[i]<<" ";
    }
    return 0;
}

其中定义迭代器类型的代码vector<int>::iterator it=v.begin();可以简写为auto it = v.begin();因为这里的v.begin()类型就是一个迭代器类型,赋值后,auto会根据赋值号右边的类型赋给左边。

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

也可以使用这种方式进行遍历。

3.常用函数

(1)push_back()

push_back(item)就是在vector后面添加一个元素item

(2)pop_back()

push和pop时一对反义词,学过数据结构的人都知道,栈元素的压入和弹出就是push和pop。
须知,pop_back()一次弹出一个元素,vector容器就会减少一个预算。

(3)size()

szie()返回vector中所含元素的个数,时间复杂度为O(1)

(4)clear()

clear()用于一键清空vector中的所有元素,时间复杂度为O(N),其中N为vector中原属和元素的个数。

(5)insert()

insert(要插入的地址,要插入的元素);
与push_back()无脑在尾部添加元素不同的是,insert()是根据指定位置在vector中插入元素。

v.insert(v.begin()+2,-1); //将-1插入v[2]的位置

(6)erase()

同样,与clear()简单粗暴清空vector不同的是erase(),删除指定位置的元素。

erase()有两种用法:

删除一个元素(erase(index); )

//删除v[3]
v.erase(v.begin()+3);

删除一个区间内的元素

//删除v[1]到v[4]的元素
v.erase(v.begin()+1,v.begin()+4);

4.vector常见用途

(1)储存数据
vector本身可以作为数组使用,而且在一些元素个数不确定的场合可以很好地节省空间。

(2)用邻接表存储图
使用vector实现邻接表,更为简单。

二、set

1.set的定义

像定义变量一样定义set变量:

set<类型名> 变量名;

类型名可以是int、double、char、struct,也可以是STL容器:vector、set、queue。

用例:

set<int> name;
set<double> name;
set<char> name;
set<struct node> name;
set<set<int> > name;//注意:> >之间要加空格

set数组的定义和vector相同:

set<类型名> array[SIZE];

例如:

set<int> arr[10];

2.set容器内元素的访问

set只能通过迭代器(iterator)访问:

set<int>::iterator it;
set<char>::iterator it;

这样,就得到了迭代器it,并且可以通过*it来访问set里的元素。

注意:

除了vector和string之外的STL容器都不支持*(it+i)的访问方式,因此只能按照如下方式枚举:

int main()
{
	set<int> st;
	st.insert(5);
	st.insert(2);
	st.insert(6);
	for (set<int>::iterator it = st.begin(); it != st.end(); it++)
	{
		cout << *it << endl;
	}
return 0;
}

set内部的元素会自动递增排序,并且晒去了重复元素。

3.常用函数

  1. 插入元素 (insert())
    使用insert()函数可以向set中插入一个元素。
set<char> st;  
st.insert('A');
  1. 查找元素 (find())
    当查找一个不存在的元素时(比如数字2),find()会返回end()迭代器,你不能直接解引用它,否则会引发错误。你应该先检查find()的返回值是否等于end()
set<char>::iterator it = st.find('A'); 
if (it != st.end()) {  
    cout << *it << endl;  
} else {  
    cout << "Element not found" << endl;  
}

或者使用*(st.find('A'))的方式,但同样需要先检查返回值。

  1. 删除元素 (erase())
    如果删除一个不存在的元素(如st.find(100)),find()将返回end(),你不能直接传递给erase()
// 删除单个元素  
set<char>::iterator it = st.find('A');  
if (it != st.end()) {  
    st.erase(it);  
}  
  
// 删除区间元素  
it = st.find('some_value');  
if (it != st.end()) {  
    st.erase(it, st.end());  
}

注意,删除区间元素时,你需要确保find()返回的迭代器不是end(),否则你不能从end()迭代器开始删除。

  1. 获取元素个数 (size())
    size()函数返回set中的元素个数,时间复杂度为O(1)。
cout << st.size() << endl;
  1. 返回元素 (begin()end())
    begin()返回指向set中第一个元素的迭代器,而end()返回指向set“尾部之后”的迭代器。你不能解引用end()返回的迭代器,它通常用作一个哨兵值,表示序列的结束。
if (!st.empty()) {  
    cout << *st.begin() << endl; // 输出第一个元素  
}
  1. 判断容器是否为空 (empty())
    这部分是正确的。empty()函数返回一个布尔值,表示set是否为空。
if (st.empty()) {  
    cout << "The set is empty" << endl;  
} else {  
    cout << "The set is not empty" << endl;  
}

4.自定义比较函数

  1. 元素不是结构体

    struct myComp {
    	bool operator()(const int &a,const int &b) {
    		return a-b>0;
    	}
    };
    set<int,myComp>s;
    
    int main() {
    	s.insert(1);
    	cout<<s.size();
    }
    
  2. 元素是结构体类型

struct Info {
	string name;
	float score;
	//重载“<”操作符,自定义排序规则
	bool operator < (const Info &a) const {
		//按score从大到小排列
		return a.score<score;
	}
};
set<Info> s;
int main() {
	Info t;
	t.name="zhangsan";
	t.score=1.0;
	s.insert(t);
	set<Info>::iterator a=s.begin();
	cout<<(*a).name<<" "<<(*a).score;
}

三、map

map是STL(中文标准模板库)的一个关联容器。

  1. 可以将任何基本类型映射到任何基本类型。如char array[100]事实上就是定义了一个int型到char型的映射。
  2. map提供一对一的数据处理,key-value键值对,其类型可以自己定义,第一个称为关键字,第二个为关键字的值
  3. map内部是自动排序的

1.定义

map<type1name,type2name> maps;//第一个是键的类型,第二个是值的类型

map<string,int> maps;

2.访问

  • 通过下标访问:

    • 如:maps["as"]=5;
  • 迭代器访问:

    •   int main()
        {
        	map<char,int> maps;
        	maps['A']=1;
        	maps['B']=2;
        	maps['C']=3;
        	for(map<char,int>::iterator it = maps.begin();it!=maps.end();it++)
        	{
        		cout<<it->first<<" "<<it->second<<endl;
                //使用it->first来访问键,使用it->second访问值
        	}
         } 
      

3.常用函数

  • maps.insert() 插入

    •   maps.insert(pair<char,int>('D',4));
        maps.insert(map<char,int>::value_type('E',5));
      
  • maps.find()查找

    •   cout<<(maps.find('A'))->first;
      
  • maps.clear()清空

  • maps.erase()删除元素

    •   maps.erase(maps.find('A'));//迭代器删除
        int t = maps.erase('B');//成功删除返回1
      
  • maps.empty()判断其是否为空

  • maps.swap()交换两个map

    •   maps.swap(map1);
      
  • maps.begin()返回指向map头部的迭代器

  • maps.end()返回指向map末尾的迭代器

  • maps.size()长度

posted @ 2024-03-20 13:02  YJQING  阅读(18)  评论(0)    收藏  举报