C++基础用法

容器

vector

定义

#include <vector>
using namespace std;
vector<type> name;                            //type为数据类型,如int,string等,name为vector标识

访问

  1. 通过下标访问

  2. 通过迭代器访问

    vector<type>::iterator it;
    

    例如:

    vector<int>::iterator it = vi.begin();
    for(int i = 0; i < 5; ++i) {
        printf("%d", *(it+i));                //或者使用it++和++it访问,同理
    }
    

    常用的STL容器中,只有在vector和string中允许使用name.begin()+i这种迭代器加上整数的写法。

函数

name.back();                                //获取vector末尾内容
name.pop_back();                            //vector中弹出末尾内容
name.push_back(temp);                        //将temp添加到vector末尾,temp必须是type类型
name.empty();                                //判空,返回int,空则返回1
name.insert(it, temp);                        //在it迭代器位置插入temp
name.erase(it);                                //删除it处的单个元素
name.erase(first, last);                    //删除[first, last)内的所有元素,first会被删除,last不会
name.begin();                                //获取vector首元素的地址,返回int
name.end();                                    //获取vector尾元素的下一个地址,返回int
name.size();                                //获得vector中元素的个数,返回unsigned
name.clear();                                //清空vector中的所有元素

//复制vector内容
vector<int> list1;
vector<int> list2;
vector<int> list2(list1);                                //定义时 list2 内容复制 list1,不影响 list1
list2.assign(list1.begin(), list1.end());                //将 list1 的内容复制到 list2,不影响 list1,复制内容的迭代器可自定义
list2.swap(list1);                                        //将 list1 内容移动到 list2,list1 为空
list2.insert(list2.end(), list1.begin(), list1.end());        //将 list1 的内容插入到 list2 末尾,插入位置和插入内容的迭代器可自定义

string

定义

#include <string>
using namespace std;
string name;                                //定义一个string
string name = "abcd";                        //定义一个string并初始化赋值

访问

  1. 通过下标访问:

    读入和输出string只能用cin和cout,在iostream头文件中

    如果要用printf输出string,则需要用c_str()转换,如printf("%s", name.c_str())

  2. 通过迭代器访问

    for(string::iterator it = st.begin(); it != st.end(); ++it) {
        printf("%c", *it);
    }
    

函数

name.size();                                //求string长度
name.length();                                //求string长度
name.substr(pos, len);                        //求pos开始长度为len的子串,返回string
name.append(string temp);                    //将temp插入到name后面
name.insert(pos, string);                    //在pos号位置插入string
name.insert(it, it2, it3);                    //将串[it2,it3)插入到it位置上
name.erase(it);                                //删除it位置单个元素
name.erase(first, last);                    //删除[first,last)
name.erase(pos, length);                    //删除pos开始长度为length的字符
name.clear();                                //清空string
name.find(str);                                //返回str在name中第一次出现的位置,若不是name的子串则返回string::npos
name.find(str, pos);                        //从name的pos号位开始匹配str
name.replace(pos, len, str);                //从pos号位开始长度为len的子串替换为str
name.replace(it1, it2, str);                //迭代器[it1, it2)的子串替换为str
str3 = str1 + str2;                            //将str1和str2拼接并赋值给str3
name.pop_back();                            //删掉末尾元素

两个string类型可以直接用==, !=, <, <=, >, >=比较大小,比较规则是字典序。

string::npos是一个常数,值为-1,由于是unsigned_int类型,实际上也是4294967295.

set

定义

内部自动有序且不含重复元素的容器。

#include <set>
using namespace std;
set<type> name;

//将vector去重放入set
vector<int> nums;
unordered_set<int> st(nums.begin(), nums.end());

访问

set只能通过迭代器访问:

set<type>::iterator it;

例如:

for(set<int>::iterator it = st.begin(); it != st.end(); ++it) {        //set不支持it < st.end()这种写法
    printf("%d", *it);
}

函数

name.insert(x);                                //x插入set容器,并自动递增排序和去重
name.find(value);                            //返回值为value的迭代器
name.erase(it);                                //删除迭代器it的元素
name.erase(value);                            //删除值为value的元素
name.erase(first, last);                    //删除[first, last)内的所有元素,first会被删除,last不会
name.size();                                //返回set内元素的个数
name.clear();                                //清空set

set中元素是唯一的,如果需要处理元素不唯一的情况,则需要使用multiset。C++11标准中还增加了unordered_set,以散列代替set内部的红黑树实现,可以处理只去重但不排序的需求,速度比set快。

queue

定义

#include <queue>
using namespace std;
queue<type> name;

访问

只能通过 front() 访问队首元素,或者通过 back() 访问队尾元素。

函数

name.push(x);                                //将x入队
name.emplace(x);                            //将x入队
name.front();                                //获得队首元素
name.back();                                //获得队尾元素
name.pop();                                    //令队首元素出队
name.empty();                                //判空,空则返回true
name.size();                                //返回队内元素个数

延伸

priority_queue优先队列

定义

优先队列底层是用堆来实现的,队首元素一定是优先级最高的一个。

#include <queue>
using namespace std;
priority_queue<type> name;

访问

只能通过top()函数访问队首元素。

函数

name.emplace(x);                        //令x入队
name.top();                            //获得队首元素,top前必须先用empty判空,否则会因为队空出错
name.pop();                            //令队首元素出队
name.empty();                        //判空,空则返回true
name.size();                        //返回队内元素个数

优先级

  1. 对于基本数据类型(int、char、double等)一般是数字大的优先级高。

    priority_queue<int> q;
    priority_queue<int, vector<int>, less<int>> q;
    

    这两种定义等价,vector指名了承载数据的容器,less表示数字大的优先级大,greater表示数字小的优先级大。

  2. 对于结构体的优先级设置,例如:

    struct fruit {
        string name;
        int price;
    };
    

    如果希望水果价格高的优先级高,需要重载(overload)小于号“<”:

    struct fruit {
        string name;
        int price;
        friend bool operator < (fruit f1, fruit f2) {        //friend为友元
            return f1.price < f2.price;
        }
    };
    priority_queue<fruit> q;                            //定义一个结构体队列,此时价格高的水果优先级高
    

    如果希望价格低的水果优先级高:

    struct fruit {
        string name;
        int price;
        friend bool operator < (fruit f1, fruit f2) {        //friend为友元
            return f1.price > f2.price;                    //使用了大于号
        }
    };
    priority_queue<fruit> q;                            //定义一个结构体队列,此时价格低的水果优先级高
    

    写在结构体外面时类似sort中的cmp函数:

    struct cmp {
        bool operator () (fruit f1, fruit f2) {            //去掉friend,把小于号改成一对小括号
            return f1.price > f2.price;
        }
    };
    priority_queue<fruit, vector<fruit>, cmp> q;        //此时只能使用第二种定义方式
    

    这种方式不止适用结构体,基本数据类型和其他STL容器也可以这样定义。

    同时数据庞大时也可以使用引用来提高效率:

    friend bool operator < (const fruit &f1, const fruit &f2) {
        return f1.price > f2.price;
    }
    bool operator () (const fruit &f1, const fruit &f2) {
        return f1.price > f2.price;
    }
    

    优先队列常用于解决贪心问题。

deque双端队列

定义

deque<type> name;                            //type为数据类型,name为deque标识

函数

name.push_back(temp);                        //temp入队
name.front();                                //取队头元素,返回type类型
name.pop_front();                            //队头元素出队

stack

定义

栈是容器适配器,底层可以用deque、vector、list实现,默认是deque,deque在内存中是不连续的。

#include <stack>
using namespace std;
stack<type> name;

访问

只能通过top()来访问栈顶元素。

函数

name.push(x);                                //元素x入栈
name.top();                                    //获得栈顶元素
name.pop();                                    //弹出栈顶元素
name.empty();                                //判空,空则返回true
name.size();                                //返回栈内元素个数

pair

定义

#include <utility>                            //map头文件会包含utility头文件,如果已添加map则不需要再添加utility
using namespace std;
pair<type1, type2> name;

初始化的两种方式:

pair<string, int> p("haha", 5);                //定义的同时可以初始化
make_pair("haha", 5);                        //使用函数初始化

访问

pair中只有两个元素,按结构体的方式访问即可:

name.first
name.second

函数

两个pair类型可以直接使用==, !=, <, <=, >, >=比较大小,规则是先以first比较大小,first相等时以second比较大小。

map

定义

#include <map>
using namespace std;
map<type1 ,type2> name;                        //type1映射到type2

访问

  1. 通过下标访问

  2. 通过迭代器访问:

    map<type1, type2>::iterator it;
    it->first;                                //访问键
    it->second;                                //访问值
    

函数

name.count(temp);                            //在name中统计temp的数量
name.find(key);                                //返回键为key的迭代器
name.erase(it);                                //删除单个元素
name.erase(key);                            //删除键对应的映射
name.erase(first, last);                    //删除[first, last)内的所有元素,first会被删除,last不会
name.size();                                //获得map中映射的数量
name.clear();                                //清空map

由于map内部用红黑树实现,所以会按照键从小到大自动排序。

map的键和值是唯一的,处理一个键对应多个值的情况用multimap,C++11中增加了unordered_map,以散列代替内部的红黑树实现,可以不按key排序,速度比map快。


常用函数

math

#include<math.h>
fabs(double x);                                //取x的绝对值
floor(double x);                            //向下取整
ceil(double x);                                //向上取整
pow(double r, double p);                    //返回r的p次方
sqrt(double x);                                //返回x的算术平方根
log(double x);                                //返回以自然对数为底的对数(没有任意底数求对数的函数)
sin(double x); cos(double x); tan(double x);//正弦,余弦,正切,参数是弧度(nΠ/180)
asin(double x); acos(double x); atan(double x);    //反正弦,反余弦,反正切
round(double x);                            //四舍五入

随机数

#include <stdlib.h>
#include <time.h>
srand((unsigned)time(NULL));
rand();                                        //返回一个0到RAND_MAX范围内的整数

数字转化字符串

to_string(int num);                            //num转化为字符串并返回一个string

algorithm头文件下的常用函数

max(x, y)、min(x, y)

返回x和y中的最大值和最小值,参数必须是2个

abs(x)

返回x的绝对值,x必须是整数,如果是浮点型要使用math头文件下的fabs

swap(x, y)

交换x和y的值。

reverse(it1, it2)

将数组指针在[it1, it2)之间的元素或容器的迭代器在[it1, it2)范围内的元素反转。

next_permutation()

给出一个序列在全排列中的下一个序列(不会给出当前序列,所以通常用do...while循环),到达全排列的最后一个时会返回false。

fill(from, to, value)

将数组或容器中某一段区间赋值为value。

sort(from, to, cmp)

from是排序的首元素地址,to是尾元素地址的下一个地址,这两个是必填参数;cmp是比较函数,非必填,不填时默认为递增排序。

#include <algorithm>
using namespace std;
sort(from, to, cmp);                        //from为排序起始地址,to为结束地址,cmp为比较函数
例如:sort(strs.begin(), strs.end(), [](string& x, string& y){ return x + y < y + x; });
                                            //strs为vector<string>

cmp函数实现:

/* 基本数据类型 */
bool cmp(int a, int b) {
    return a > b;                            //a > b时把a放在b前面,即从大到小排序
}

/* 结构体 */
struct node {
    int x, y;
}a[10];
bool cmp(node a, node b) {
    return a.x>b.x                            //按x从大到小排序
}
bool cmp(node a, node b) {
    if(a.x != b.x) return a.x > b.x;
    else return a.y < b.x;                    //按x从大到小排序,x相等时按y从小到大排序
}

/* 容器排序,只有vector,string,deque可以使用sort */

lower_bound(first, last, val)、upper_bound(first, last, val)

寻找数组或容器在[first, last)范围内第一个值大于等于val和大于val的元素的位置,数组则返回指针,容器则返回迭代器,未找到时返回可以插入该元素的位置。

程序执行时间统计

#include <chrono>
using namespace chrono;
int time_consumption() {
    milliseconds start_time = duration_cast<milliseconds>(
        system_clock::now().time_since_epoch()
    );
    func();                                                                        //需要统计的函数
    milliseconds end_time = duration_cast<milliseconds>(
        system_clock::now().time_since_epoch()
    );
    return milliseconds(end_time).count() - milliseconds(start_time).count();        //单位ms
}
posted on 2024-08-20 17:50  未连接到互联网  阅读(2)  评论(0编辑  收藏  举报