C++ STL常见用法

C++_STL

容器

包括string类,顺序容器,容器适配器,关联容器

string

创建与初始化

string a="adwdad";
string a[4] = {"twenty", "thirty", "forty", "fifty"};
    
//下面两行的写法是错的!!!
string b[4] = {'twenty', 'thirty', 'sdfse', 'dawd'};
string a='adwdad';

char s='a';
char s="a"; //这种写法是错的
char s[]="abcd";  //这个是字符串,以'\0'结束的,用strlen(s)是4,'\0'不计,但是它是有五个字符的
char s1[]={'a','b','c','d'};  //这个是字符数组,没有'\0',用strlen(s1)是不确定的,它有四个字符
char s='a';

操作

//获取字符串长度 
    int L =str.length();
    int S =str.size(); //L=S 基本一样
//str去除元素
    str.erase(pos,len);  //str.erase(0,1); //删除pos开始的lin个字符
    str.erase(a,b); //删除迭代器a和b标记范围内所有的元素,返回一个迭代器,指向被删除元素段后面的第一个元素
//string翻转
    reverse(str.begin(),str.end()); 
//string插入元素
    str.insert(pos,s2); 	//在下标为pos的元素之前插入string对象s2的副本
    str.insert(pos,n,c); 	//在下标为pos的元素之前插入n个字符c
//子串
    str.substr(pos,n); 	    //返回一个string类型的字符串,它包含s中从下标pos开始的n个字符
    str.substr(pos); 	    //返回一个string类型的字符串,它包含从下标pos开始到s末为的所有字符
//查找
    str.find(args); 	                //在s中查找args的第一次出现
    str.find(char c='a'); 	                //在s中查找字符的第一次出现
    str.find(string substr='abdb'); 	    //在s中查找子字符串的第一次出现
    str.rfind(args); 	            //在s中查找args的最后一次出现
    str.find_first_of(args);         //在s中查args的任意字符的第一次出现
    str.find_last_of(args); 	        //在s中查找args的任意字符的最后一次出现
    str.find_first_not_of(args); 	//在s中查找第一个不属于args的字符
    str.find_last_not_of(args); 	    //在s中查找最后一个不属于args的字符
    //arg的各种情况:
    c,pos 	    //在s中,从下标pos标记的位置开始,查找字符c、pos的默认值是0
    s2,pos 	    //在s中,从下标pos标记的位置开始,查找string对象s2,pos的默认值为0
    cp,pos 	    //在s中从下标pos标记的位置开始,查找cp所指向的c风格的以空格结束的字符串。pos默认值为0
    cp,pos,n 	//在s中,从下标pos标记的位置开始,查找指针cp所指向数组的前n个字符,pos和n都没有默认值
    //返回的是元素下标:eg
    size_t nLoc = str.find(args);
    if (nLoc != string::npos)   //未找到返回-1
        cout << "nLoc is: " << nLoc << endl;
//比较compare
    s.compare(s2); 	                //比较s和s2
    s.compare(pos1,n1,s2); 	        //让s中从pos下标位置开始的n1个字符与s2做比较
    s.compare(pos1,n1,s2,pos2,n2); 	//让s中从pos1下标位置开始的n1个字符与s2中从pos2下标位置开始的n2个字符做比较
    s.compare(cp);	            //比较s和cp所指向的以空字符结束的字符串
    s.compare(pos1,n1,cp); 	    //让s从pos1下标位置开始的n1个字符与cp所指向的字符串做比较
    s.compare(pos1,n1,cp,n2); 	//让s中从pos1下标位置开始的n1个字符与cp所指向字符串的前n2个字符做比较
    //结果:
    s1.compare(args);
        //a.正数,此时s1大于args所代表的string对象
        //b.负数,此时s1小于args所代表的string对象
        //c.0,此时s1恰好等于args所代表的string对象
//追加append
    s1 += s2;
    s1.append(s2);
    s1.append(s2, 5, 5);  //取s2的第5个开始的5个字符追加给s1
    s1.append(3, '!');   //s1尾部叠加3个!

常用代码块


//int转string
    int a;
    string str = to_string(static_cast<long long>(a));
//string转int
    a=atoi(str.c_str()); 


//遍历string可以这样写,balabala
for(char c in s){
    if(c=='a'){}
}

//字符范围判断相关代码块
    for (size_t i = 0; i < str.size(); i++)
    {
        if( str[i]>='a' && str[i]<='z' ) //a to z
        if( str[i]>='A' && str[i]<='Z' )
        if( (str[i]>='a' && str[i]<='z') || (str[i]>='A' && str[i]<='Z') )
        if( str[i]>='0' && str[i]<='9' )
    }
    //不等式
    'a'<=str[i]<='z'//这样写是错的
    str[i]>='a' && str[i]<='z' //这样才是正确语法
    //等式
    if(str[i]=' ')  //这个写法错误
    if(str[i]==' ') //这样才是正确语法

vector

特性

  • 底层为连续数组,顺序结构存储
  • 自动内存管理,动态改变长度,随着元素的添加和删除而增大与缩小
  • 可以快速随机访问任意位置元素O(1)
  • 尾部添加和删除元素的时间是固定的O(1)
  • 头部或中间插入和删除元素的复杂度为O(n),需要移动其他元素

头文件

#include <vector>

定义与初始化

vector<int> Excel;
vector<int> Excel = {1,2,3,4};
vector<vector<int>> Excel = {{1,2},{1,2,3,4}};
vector<int> v(7,3);  //指定值初始化,v被初始化为包含7个值为3的int
vector<int> v(5);
itoa(v.begin(), v.end, 2)  //v初始化为{2,3,4,5,6}

操作

方法说明
T front()返回首元素的引用
back返回尾元素的引用
begin返回指向首元素的随机存取迭代器
end返回指向尾元素的下一个位置的随机存取迭代器
push_back表尾巴添加元素
emplace_back表尾巴添加元素(传入构造函数的参数)
pop_back删除尾元素
insert插入
erase删除
size()元素个数
clear清空
empty判空
resize
swap
assign
//添加元素
    Excel.push_back(nums);
    vector<pair <int, string>> v;
    v.emplace_back(3, "abc");
//去除元素
    int nPosition = i;//元素脚标
    Excel.erase(Excel.begin()+nPosition);
    Excel.erase(Excel.end()-1);   //注意::最后一个元素是Deriction.end()-1!

常用代码块

//--查找find
//查找的重载
class error
{
public:
    string file_name;
    int line;
    int count;
    /vector 的find函数,当vector中为自定义类型时,需要重载==操作,如下语句
    bool operator == (const error & obj) const //重载 “==” 操作符,函数最后的 const 别忘了,否则会报错。(详见:http://www.cnblogs.com/SZxiaochun/p/7731900.html)
    {
        return file_name == obj.file_name && line == obj.line; //具体匹配条件,自己设定
    }
};
    //迭代器查找
    error error_in;
    vector<error> errorlist; 
    //注意!!!!vector的find函数的使用方法不是v.find()!!!!
    vector<error>::iterator result = find( errorlist.begin( ), errorlist.end( ), error_in ); 
    if ( result == errorlist.end( ) ) //没找到
        errorlist.push_back(error_in);
    else //查找到
    {
        int nPosition = distance(errorlist.begin(), result);
	    errorlist[nPosition].count++; 
    }



//--排序sort
    //排序
    sort(Excel.begin(),Excel.end());

 //自定义类型的排序重载
 //方式1
    class Words
    {
    public:
        string strwords;
        int letter[26]={ 0 };

        ///自定义类型时,需要重载<操作,如下语句
        bool operator < (const Words & obj) const //重载 “<” 操作符,函数最后的 const 别忘了,否则会报错。(详见:http://www.cnblogs.com/SZxiaochun/p/7731900.html)
        {
            return strwords < obj.strwords; //具体匹配条件,自己设定
        }
    };
    sort(Excel.begin(),Excel.end());
 //方式2
//或者自定义函数
    bool cmp(Words a,Words b)
    {
        if(a.zfc<b.zfc)
            return true;
        else if(a.zfc==b.zfc)
            return a.a<b.a;
        else
            return false;
    } 
    sort(Deriction.begin(),Deriction.end());  //注意::字典一定要排序
    sort(Deriction.begin(),Deriction.end().cmp);
//方式1
//其他方式
    struct tree
    {
        string zfc;
        int a;
        //重载 “<” 操作符
        bool operator<(const tree &a) 
        {
            //自定义条件
            if(zfc<a.zfc)
                return true;
            else if(zfc==a.zfc)
                return this->a<a.a;
            else
                return false;
        }
    };
//方式2
//或者自定义函数
    bool cmp(tree a,tree b)
    {
        if(a.zfc<b.zfc)
        return true;
        else if(a.zfc==b.zfc)
        {
            return a.a<b.a;
        }
        return false;
    } 
int main()
{
    tree t[3];
    t[0].zfc="hh";
    t[0].a=1;
    t[1].zfc="xx";
    t[1].a=2;
    t[2].zfc="hh";
    t[2].a=0;
    sort(t,t+3); //使用sort可以重载元素类型的比较符号
    sort(t,t+3,cmp);  //也可以自己写新的排序函数
}


    //最大元素
    max_element() //返回范围内最大元素的迭代器
    vector<int>::iterator max_e = max_element(candies.begin(), candies.end());
    int max_num = *max_e;

stack

特性

  • 底层默认vector
  • 不允许随机访问栈元素
  • 不允许遍历队列,只允许访问栈顶元素

头文件

#include <stack>

创建

stack <int> stk;
//初始化
stack <int> stk = ;

操作

方法说明
bool empty()const判空
size_type size()const元素个数
T& top()返回栈顶元素的引用
void push(const T& x)栈顶插入元素
void pop()删除栈顶元素
stk.push(7);  //入栈
stk.pop();    //出栈
stk.top();    //访问栈顶元素
stk.empty();  //判空
stk.size();   //元素个数

queue

头文件

#include <queue>

创建

queue <int> q;
//初始化
queue <int> q  =;

操作

q.push(7);   //入队
q.pop();     //出队列
q.front();   //访问队首元素
q.back();    //访问队尾元素
q.empty();   //判空
q.size();    //返回队中元素个数

dqueue(双端队列)

特性

  • 头部或尾部添加和删除元素的时间是固定的O(1)
  • 支持随机访问,可以访问任意位置元素,且比vector稍慢
  • 中间插入和删除元素的复杂度为O(n),且比vector稍慢

queue(队列)

特性

  • 底层默认为dqueue
  • 不允许随机访问元素
  • 不允许遍历队列,只允许访问队首和队尾元素

头文件

#include<queue>

创建

queue<int> q;

操作

方法说明
bool empty()const判空
size_type size()const元素个数
T& front()返回队首元素的引用
T& back()返回队尾元素的引用
void push(const T& x)队尾插入元素
void pop()删除队首元素

priority_queue

特性

  • 底层默认为vector
  • priority_queue支持的操作与queue一样
  • priority_queue最大的元素被移动到队首,可以自定义比较大小的函数greater()

头文件

#include<queue>

创建

priority_queue<int> pq1;
priority_queue<int> pq1(greater<int>); //自定义比较大小的函数greater()

list(双向链表)

特性

  • 访问元素较慢O(n),不支持随机访问
  • 任意位置插入和删除的时间固定O(1),而vector为O(n)

头文件

#include <list>

创建

list<int> c0; //空链表
//初始化
list<int> c0{1,2,3,4,5};
list<int> c1(3); //建一个含三个默认值是0的元素的链表
list<int> c2(5,2); //建一个含五个元素的链表,值都是2
list<int> c4(c2); //建一个c2的copy链表
list<int> c5(c1.begin(),c1.end()); c5含c1一个区域的元素[_First, _Last)。

操作

c.begin();   //返回指向链表第一个元素的迭代器
c.end();     //返回指向链表最后一个元素之后的迭代器
1     list<int> a1{1,2,3,4,5};
2     list<int>::iterator it;
3     it = a1.begin();
4     cout << *it << endl;
c.rbegin()   //返回逆向链表的第一个元素,即c链表的最后一个数据。
c.rend()     //返回逆向链表的最后一个元素的下一个位置,即c链表的第一个数据再往前的位置。
c.front()    //返回链表c的第一个元素。
c.back()     //返回链表c的最后一个元素。
c.empty()    //判断链表是否为空。
c.size()     //返回链表c中实际元素的个数。
c.insert(pos,num)      //在pos位置插入元素num。
c.insert(pos,n,num)    //在pos位置插入n个元素num。
c.insert(pos,beg,end)  //在pos位置插入区间为[beg,end)的元素。
c.erase(pos)          //删除pos位置的元素。
c.push_back(num)       //在末尾增加一个元素。
c.pop_back()           //删除末尾的元素。
c.push_front(num)      //在开始位置增加一个元素。
c.pop_front();          //删除第一个元素。
c.reverse();       //反转链表
c.unique();       //删除相邻的元素
c.sort()       将链表排序,默认升序
c.sort(comp)       自定义回调函数实现自定义排序
 1     list<int> a1{1,3,2,5,4};
 2     a1.sort();
 3     list<int>::iterator it;
 4     cout << "sort():";
 5     for(it = a1.begin();it!=a1.end();it++){
 6         cout << *it << " ";
 7     }
 8     cout << endl;
 9     
10     a1.sort([](int n1,int n2){return n1>n2;});
11     cout << "sort(function point):";
12     for(it = a1.begin();it!=a1.end();it++){
13         cout << *it << " ";
14     }
15     cout << endl;
自定义链表-struct结构
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = (node->next)->val;
        node->next = node->next->next;
    }
};

map

特性

  • 查找非常迅速 o(1)
  • 支持随机访问
  • 支持迭代器遍历
  • 注意:map遍历的时候会自动根据key的大小排序!并不代表插入顺序!

头文件

#include<map>

创建

map<typename1, typename2> mp;
map<string, int> mp;

操作

//访问元素
    map<string, int> mp;
    mp["apple"] = 15;
    mp["bnanana"] = 16;
    //方式一:直接访问
    cout<<mp["bnanana"]<<endl;
    //方式二:.at()访问,更安全
    cout<<mp.at("bnanana")<<endl;
    //方式三:通过迭代器访问
    //map 可以使用 itr->first 来访问键, itr->second 来访问值。
    for(map<char, int>::iterator itr = mp.begin(); itr != mp.end(); itr++)
            cout<< itr -> first
                << itr -> second<<endl;

//查找
find()//返回迭代器
    map<string, int>::iterator itr = mp.find("bnanana");
    cout<< itr->first << itr->second<<endl;
//删除
erase()
    map<string, int>::iterator itr = mp.find("bnanana");
    mp.erase(itr);              //删除该迭代器所指元素
    mp.erase(mp.begin(), itr);  //删除最开始到itr所指元素前的所有元素,前闭后开
    mp.erase(itr, mp.end());    //删除it之后的所有元素
    mp.erase(mp.begin());       //删除最开始的元素
    mp.erase(--mp.end());       //删除最后面的元素
//清空
    mp.clear();
//大小
    mp.size();

unordered_map

头文件

#include<unordered_map>

特性

  • 支持遍历
  • 注意:内部哈希表,遍历顺序并不代表插入顺序

map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。

map:
优点:
有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高
缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
适用处:对于那些有顺序要求的问题,用map会更高效一些

unordered_map:
优点: 因为内部实现了哈希表,因此其查找速度非常的快
缺点: 哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map

总结:
内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。
但是unordered_map执行效率要比map高很多
对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的

算法

头文件

#include <algorithm>

函数
去重

unique() 
unique(A.begin(),A.end())
//unique将相邻的重复元素移动到末尾,并不是直接删除,
//注意"相邻的",所以要先进行排序,保证重复元素相邻
//unique() 的返回值就是被后置元素的“首地址”(迭代器)
重载运算符

operator==
operator!=
operator<
operator<=
operator>
operator>=

算法思想–递归


/*
递归问题
3个瓶子换1瓶水+1个空瓶子,两个瓶子换1瓶水+0个空瓶子,1个瓶子换0瓶水。
f(1) = 0
f(2) = 1
f(3) = 1
f(4) = f(2)+1    //4个瓶子,其中3个可以换1瓶水+1个空瓶,所以是f(2)+1
f(5) = f(3)+1    //3个瓶子换1瓶水+1个空瓶,所以是f(3)+1
...
f(n) = f(n-2)+1 */

int f(int n)
{
    if(n==1) return 0;
    if(n==2) return 1;
    return f(n-2)+1;
}

int main()
{
    int n;
    while(cin >> n)
    {
        if(n==0)
            break;
        cout<<f(n)<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值