Loading

STL

STL(标准模板库)

Intro

下面会介绍很多C++STL库里面的模板,在编程中STL犹如神器,实用简洁好用。STL绝对让你受益无穷!

1.vector(动态数组)

向量容器vector是一个动态数组内存连续,它是动态分配内存,且每次扩张为原来的两倍

image-20230627191834966

1.1 Header File

#include <vector>

1.2 Definition

//a.定义 vector<typeName> v;
vector<int> v1;
//b.拷贝构造 
vector<int> v2(v1);
//c.赋值拷贝, 如果v1的size比v2的size大, 会自动扩充v2的空间, 反之亦然
v2 = v1; 
//d.按指定元素个数定义, v3含有5个为0的元素
vector<int> v3(5);
//e.指定元素个数和值, v4含有5个为10的元素 
vector<int> v4(5, 10);
//f.初始化中有多个元素
vector<int> v5{1, 2, 3, 4, 5};
//g.与array之间的转换 
int a[3] = {0, 1, 2};
vector<int> v6(a, a+3);

1.3 Use

vector<int> v;
//在vector尾部插入元素
//但是没有在前面插入元素, 上面的图示可以看出, vector是一种向后扩充的容器
//如果在前面插入, 需要将后面的所有元素后移, 造成巨大的消耗, 所以没有push_front() 
//同理也没有pop_front()
v.push_back(1);
//删除最后一个元素
v.pop_back();
//返回元素个数 
int size = v.size();
//重置size 
v.resize(2*(v.size()));
//判断容器是否为空 
bool bEmpty = v.empty();
//下标访问
int tmp = v[1];
//定义迭代器, 指向第一个元素
vector<int>::iterator iter = v.begin();
//头部插入两个5
v.insert(iter, 2, 5);
//头部插入3 
v.insert(v.begin(), 3);
//尾部插入3 
v.insert(v.end(), 3);
//下标为5的插入元素3 
v.insert(v.begin()+5, 3);
//删除指定元素下标
v.erase(v.begin()+5);
//清空 
v.clear();
//起始地址
v.begin();
//最后一个元素后面的地址
v.end();
//实际内存大小
v.capacity();
//返回指定下标元素
v.at(1);
//返回第一个元素
v.front();
//返回最后一个元素
v.back();
//将3个1赋值给vector
v.assign(3, 1);
//将指定区间内的元素赋值给vector
v.assign(v.begin()+1, v.begin()+3);
//最大内存
v.max_size();
//智能指针 
for(auto i : v)
    cout << i << endl;

1.4 Memory Management

vector的扩充是以2倍的形式扩充,它的扩充过程可以理解成 if(v.size()元素个数 > v.capacity()实际内存) v.resize(2*v.capacity());当vector发现元素个数大于实际内存时,vector将重新申请一块内存为原来的内存2倍的空间,然后将原来的元素一一copy过去,我们都知识申请内存是非常耗时的,所以我们一定要把握好vector的内存尺度。

void vector_test_capactity()
{
    //创建vector
    std::vector<int> v;
    for (int i = 0; i < 10; i++) {
        cout << "容器内元素个数:" << v.size() << " " << "vector内存大小:" << v.capacity() << endl;
        v.push_back(i);
    }
}

1.5 Source Code

template<typename _Tp, typename _Alloc>
    struct _Vector_base
    {
        typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
        rebind<_Tp>::other _Tp_alloc_type;
        typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
        pointer;

        struct _Vector_impl
        : public _Tp_alloc_type
        {
            pointer _M_start;
            pointer _M_finish;
            pointer _M_end_of_storage;
            ...
        }

        pointer
        _M_allocate(size_t __n)//申请内存
        {
            typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
            return __n != 0 ? _Tr::allocate(_M_impl, __n) : 0;
        }

        void
        _M_deallocate(pointer __p, size_t __n)//释放内存
        {
            typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
            if (__p)
                _Tr::deallocate(_M_impl, __p, __n);
        }
    }

image-20230627200357071

Attention:

  • v[i]*(v.begin()+i)等价;
  • 只有vectorstringSTL容器支持*(it+i)的元素访问;

2.stack

2.1 头文件

#include <stack>

2.2 基本操作(应用)

字符串匹配问题:

#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <string>
#include <stack>
using namespace std;
int priority(char c) {		//返回c的优先级 
	if(c=='<'||c=='>')
		return 1;
	if(c=='('||c==')')
		return 2;
	if(c=='['||c==']')
		return 3;
	if(c=='{'||c=='}')
		return 4;
	return -1;
}
bool is_left(char c) {		//判断是否是左括号 
	return c=='('||c=='['||c=='{'||c=='<';
}
bool is_right(char c) {
	return c==')'||c==']'||c=='}'||c=='>';
}
//两个括号是否匹配 
bool match(char a,char b) {
	if(!is_left(a))		//如果左边的不是左括号 
		return false;
	if(a=='(')
		return b==')';
	if(a=='[')
		return b==']';
	if(a=='{')
		return b=='}';
	if(a=='<')
		return b=='>';
}
//一个一个判断 
bool func(stack<char>& s,char c,stack<int>& prioritys) {
	if(is_left(c)) {		//如果是左括号 
		if(prioritys.top()>=priority(c)) {
			s.push(c);
			prioritys.push(priority(c));
		} else {
			return false;		//优先级太高 
		}
	} else if(is_right(c)) {		//如果是右边 
		if(!s.empty()&&match(s.top(),c)) {		//如果匹配 
			s.pop();
			if(!prioritys.empty())			//非空 
				prioritys.pop();
		} else
			return false;
	}
	return true;
}
bool check(string str) {
	stack<char> s;
	stack<int> prioritys;		//优先级 
	prioritys.push(0x7fffffff);		//很大很大的数 
	for(int i=0; i<str.size(); i++) {
		char c=str[i];
		if(!func(s,c,prioritys)) {
			return false;
		}
	}
	return s.empty();
}
int main(int argc,char* argv[],char** env) {
	int n;
	cin>>n;
	getchar();		//以防把n后面的换行当成第一个字符 
	while(n--) {
		string str;
		getline(cin,str);		//保险,其实完全可以用cin>>str;
		if(check(str))
			cout<<"YES\n";
		else
			cout<<"NO\n";
	}
	return 0;
}

2.3 函数

函数 含义
s.push(n); 压栈
s.pop(); 弹栈
s.top(); 获取栈顶元素
s.empty(); 判断栈是否为空
s.size(); 返回栈中元素个数

3.queue

3.1 头文件

#include <queue>

3.2 函数

函数 含义

3.3 举例

More

References

posted @ 2023-06-20 16:34  PHASELESS!  阅读(81)  评论(0)    收藏  举报