C++语法基础--STL、位运算、常用库函数

一、STL

1、vector

vector 是一种序列容器,允许在运行时动态地插入和删除元素。使用时需要包含#include<vector>这个头文件。
    • size返回vector的实际长度,empty函数返回一个bool类型,表明vector是否为空。
    • 二者的时间复杂度都是 O(1)。所有的STL容器都支持这两个方法。
    • 迭代器就像STL容器的指针,可以用*操作符解除引用。
    • vector的迭代器是“随机访问迭代器”,可以把vector的迭代器与一个整数相加减,其行为和指针的移动类似。可以把vector的两个迭代器相减,其结果也和指针相减类似,得到两个迭代器对应下标之间的距离。
    • begin()函数返回指向vector中的第一个元素的迭代器。
    • end()函数返回vector的尾部,就是最后一个元素的下一个。
    • front()表示返回vector的第一个元素。
    • back()表示返回vector的最后一个元素。
    • push_back(x)表示在vector的末尾插入元素x。
    • pop_back()表示删除vector的末尾元素。

vector实例

#include<iostream> #include<vector> using namespace std; int main(){ // 创建vector a vector<int> a; // 添加元素 a.push_back(1); a.push_back(2); a.push_back(3); a.push_back(4); a.push_back(5); // 获取vector a 的长度并判断是否非空 int len = a.size(); bool is_empty = a.empty(); cout<<len<<" "<<is_empty<<endl; // 返回第一个和最后一个元素 int first = a.front(); int last = a.back(); cout<<first<<" "<<last<<endl; // 删除最后一个元素 a.pop_back(); // 删除指定的某个元素-----删除第三个元素 a.erase(a.begin() + 2); // 更新第一个和最后一个元素 first = a.front(); last = a.back(); cout<<first<<" "<<last<<endl; // 使用迭代器遍历vector----输出vector a中的所有元素 for(vector<int>::iterator it = a.begin(); it < a.end(); it++){ cout<< *it <<endl; } // 通过下标访问元素 cout<<a[2]<<endl; // 清空所有元素 a.clear(); // 获取vector a 的长度并判断是否非空 len = a.size(); is_empty = a.empty(); cout<<len<<" "<<is_empty<<endl; return 0; }

通过使用上述介绍的所用函数,具体展现了每一个函数的用法和作用。

push_back和pop_back函数

front和back函数

begin和end函数

迭代器

erase函数

可以使用 erase() 方法删除 vector 中的元素。

clear函数

可以使用 clear() 方法清空 vector 中的所有元素。

size和empty函数

声明

#include<iostream> #include<vector> using namespace std; int main(){ vector<int> a;//一个长度是动态变化的int数组 vector<int> b[233]; //第一维长度是233,第二维是动态变化的int数组 return 0; }

2、queue

使用时需要包含#include<queue>头文件。queue主要包括循环队列queue和优先队列priority_queue两个容器。遵循元素在队首添加,队尾移出的规则。
实例
#include<iostream> #include<queue> using namespace std; int main(){ // 创建优先队列 priority_queue<int> q; // 添加元素 q.push(1); q.push(2); q.push(3); q.push(4); q.push(5); // 创建一个临时队列m------默认是最大堆(也就是升序排列) priority_queue<int> m = q; while(m.empty() != 1){ cout<<m.top()<<endl; m.pop(); } // 删除队首元素 q.pop(); q.pop(); // 输出q队列元素 while(q.empty() != 1){ cout<<q.top()<<endl; q.pop(); } return 0; }
top函数

返回队列顶部的元素(并不删除)。

pop函数

移除队列顶部的元素。

push函数

向队列中添加一个元素。

优先队列priority_queue

实例
#include<iostream> #include<queue> using namespace std; int main(){ // 创建queue queue<int> q; // 添加元素 q.push(1); q.push(2); q.push(3); q.push(4); // 创建一个临时队列m queue<int> m = q; // 遍历所有元素 while(m.empty() != 1){ // 如果队列不为空,则输出队首元素 cout<<m.front()<<endl; // 输出之后弹出队首元素 m.pop(); } //输出q队列的队首和队尾元素 cout<<q.front()<<endl; cout<<q.back()<<endl; // 输出q队列的长度 cout<<q.size()<<endl; return 0; }
back函数

back()返回队尾元素。

front函数

front()返回队首元素。

pop函数

pop()移除队首元素。

push函数

push()在队尾添加一个元素。

循环队列queue

声明

#include<iostream> #include<queue> using namespace std; int main(){ queue<int> q; priority_queue<int> a; //大根堆 priority_queue<int, vector<int>, greater<int>> b;//小根堆 priority_queue<pair<int,int>>c; return 0; }

3、stack

使用时需要包含#include<stack>头文件。

实例

#include<iostream> #include<stack> using namespace std; int main(){ // 创建 stack<int> s; // 栈顶添加元素 s.push(1); s.push(2); s.push(3); s.push(4); // 遍历元素 stack<int> t = s; while(t.empty() != 1){ cout<<t.top()<<endl; t.pop(); } // 删除s的栈顶元素 s.pop(); s.pop(); // 删除s中的元素 while(s.empty() != 1){ cout<<s.top()<<endl; s.pop(); } return 0; }

top函数

返回栈顶元素,但不删除。

pop函数

移除栈顶元素。

push函数

在栈顶添加一个元素。

声明

4、deque

实例

#include<iostream> #include<deque> using namespace std; int main(){ // 创建队列 deque<int> q; // 添加元素 q.push_front(1); q.push_back(2); q.push_front(3); q.push_back(4); int len = q.size(); bool is_empty = q.empty(); cout<<len<<" "<<is_empty<<endl; // 遍历所有元素 for(deque<int>::iterator it = q.begin(); it < q.end(); it++){ cout<< *it <<endl; } // 删除元素 q.pop_back(); q.pop_front(); len = q.size(); is_empty = q.empty(); cout<<len<<" "<<is_empty<<endl; // 遍历所有元素 for(deque<int>::iterator it = q.begin(); it < q.end(); it++){ cout<< *it <<endl; } // 清空 q.clear(); len = q.size(); is_empty = q.empty(); cout<<len<<" "<<is_empty<<endl; return 0; }

clear函数

clear()表示清空队列

pop_front和pop_back函数

pop_front()从队头出队,pop_back()从队尾出队

push_front和push_back函数

push_front()从队头出队,push_back()从队尾入队

front和back函数

返回队头和队尾元素

begin和end函数

返回deque的头为迭代器

声明

#include<iostream> #include<deque> using namespace std; int main(){ deque<int> q; return 0; }

5、set

使用时需要包含#include<set>头文件。
    1. size()用来获取容器的长度。
    2. empty()用来判断容器是否非空。
    3. clear()用来清空容器元素。
    4. set和multiset的迭代器称为“双向访问迭代器”,不支持“随机访问”,支持星号*解除引用,仅支持++和--两个与算术相关的操作。
    5. 设it是一个迭代器,例如set<int>::iterator it;
    6. 若把it ++,则it会指向“下一个”元素。这里的“下一个”元素是指在元素从小到大排序的结果中,排在it下一名的元素。同理,若把it --,则it将会指向排在“上一个”的元素。
    7. 返回首、尾迭代器,时间复杂度均为 O(1)。
    8. s.begin()是指向集合中最小元素的迭代器。
    9. s.end()是指向集合中最大元素的下一个位置的迭代器。
    10. s.insert(x)把一个元素x插入到集合s中,时间复杂度为 O(logn)。
    11. 在set中,若元素已存在,则不会重复插入该元素,对集合的状态无影响。
    12. 这两个函数的用法与find类似,但查找的条件略有不同,时间复杂度为 O(logn)。
    13. s.lower_bound(x)查找大于等于x的元素中最小的一个,并返回指向该元素的迭代器。
    14. s.upper_bound(x)查找大于x的元素中最小的一个,并返回指向该元素的迭代器。
    15. 设it是一个迭代器,s.erase(it)从s中删除迭代器it指向的元素,时间复杂度为 O(logn)。
    16. 设x是一个元素,s.erase(x)从s中删除所有等于x的元素,时间复杂度为 O(k+logn),其中 k 是被删除的元素个数。

实例

#include<iostream> #include<set> using namespace std; int main(){ // 创建实例 set<int> s; // 添加元素 s.insert(1); s.insert(2); s.insert(3); s.insert(4); s.insert(5); // 获取长度并判断是否非空 int len = s.size(); bool is_empty = s.empty(); cout<<len<<" "<<is_empty<<endl; // 遍历元素(输出) for(set<int>::iterator it = s.begin(); it != s.end(); it++){ cout<< *it <<endl; } // 删除元素 s.erase(3); len = s.size(); is_empty = s.empty(); cout<<len<<" "<<is_empty<<endl; // 遍历元素(输出) for(set<int>::iterator it = s.begin(); it != s.end(); it++){ cout<< *it <<endl; } // 查找元素2 if(s.find(2) != s.end()){ cout<<"2 is yes"<<endl; }else{ cout<<"2 is no"<<endl; } // 输出出现的次数 int count = s.count(0); cout<<count<<endl; return 0; }

count函数

s.count(x)返回集合s中等于x的元素个数,时间复杂度为 O(k+logn),其中 k 为元素x的个数。

erase函数

lower_bound和upper_bound函数

find函数

s.find(x)在集合s中查找等于x的元素,并返回指向该元素的迭代器。若不存在,则返回s.end()。时间复杂度为 O(logn)。

insert函数

begin和end函数

迭代器

size、empty、clear函数

声明

#include<iostream> #include<set> using namespace std; int main(){ set<int> s; return 0; }

6、map

使用时需要包含#include<map>头文件

实例

#include <iostream> #include <map> #include <string> using namespace std; int main() { // 创建一个 map 容器,存储员工的姓名和年龄 map<string, int> employees; // 插入员工信息 employees.insert(make_pair("Alice",30)); employees.insert(make_pair("Bob",25)); employees.insert(make_pair("Charlie",35)); // 遍历 map 并打印员工信息 for (map<string, int>::iterator it = employees.begin(); it != employees.end(); ++it) { // it->first是键,it->second是值 cout<< it->first << ":" << it->second <<endl; } // 获取长度并判断是否非空 int len = employees.size(); bool is_empty = employees.empty(); cout<<len<<" "<<is_empty<<endl; // 查找键值 map<string, int>::iterator it = employees.find("Bob"); if(it != employees.end()){ if(it->second == 25){ cout<<"Bob: 25 is yes"<<endl; }else{ cout<<"Bob: 25 is no"<<endl; } }else{ cout<<"Bob: 25 is no"<<endl; } // 清空 employees.clear(); len = employees.size(); is_empty = employees.empty(); cout<<len<<" "<<is_empty<<endl; return 0; }

find函数

h.find(x)在变量名为h的map中查找key为x的二元组。

insert和erase函数

与set类似,但其参数均是pair<key_type, value_type>。

size、empty、clear、begin、end函数

和set类似。

声明

map容器是一个键值对key-value的映射,其内部实现是一棵以key为关键码的红黑树。Map的key和value可以是任意类型,其中key必须定义小于号运算符。

#include<iostream> #include<map> using namespace std; int main(){ map<long long, bool> vis; return 0; }

二、位运算

1、位运算

&
|
~
^异或
>>右移
<<左移

2、常见操作

lowbit(x) = x & -x,返回x的最后一位1

#include<iostream> #include<string> using namespace std; int main(){ int num; cin>>num; int lowbit = num & -num; cout<< lowbit <<endl; return 0; }

求x的第k位数字 x >> k & 1

#include<iostream> #include<string> using namespace std; int main(){ int num; cin>>num; int k ; cin>>k; cout<< ((num>>k) & 1) <<endl; return 0; }

三、常用库函数

1、reverse函数

将元素进行翻转。例子:翻转数组和vector。

#include<iostream> #include<algorithm> #include<vector> using namespace std; int main(){ int a[10] = {1,2,3,4,5,6,5,4,3,2}; for(int i = 0; i < 10; i++){ cout<<a[i]<<endl; } cout<<endl; // 翻转数组 reverse(a,a + 10); for(int i = 0; i < 10; i++){ cout<<a[i]<<endl; } cout<<endl; vector<int> q; // 添加元素 q.push_back(1); q.push_back(2); q.push_back(3); q.push_back(4); // 输出 for(vector<int>::iterator it = q.begin(); it < q.end(); it++){ cout<< *it <<endl; } cout<<endl; // 翻转vector q reverse(q.begin(),q.end()); // 输出 for(vector<int>::iterator it = q.begin(); it < q.end(); it++){ cout<< *it <<endl; } return 0; }

2、unique函数

返回去重(只去掉相邻的相同元素)之后的尾迭代器(或指针),仍然为前闭后开,即这个迭代器是去重之后末尾元素的下一个位置。该函数常用于离散化,利用迭代器(或指针)的减法,可计算出去重后的元素个数。

#include<iostream> #include<algorithm> #include<vector> using namespace std; int main(){ vector<int> q; // 添加元素 q.push_back(1); q.push_back(2); q.push_back(2); q.push_back(2); q.push_back(3); q.push_back(3); q.push_back(4); // 输出 for(vector<int>::iterator it = q.begin(); it != q.end(); it++){ cout<< *it <<endl; } cout<<endl; // 去重vector q vector<int>::iterator new_end = unique(q.begin(),q.end()); q.erase(new_end, q.end()); // 输出不重复元素的数量 int m = q.size(); cout << "Number of unique elements: " << m << endl; // 去重后的元素 cout << "After removing duplicates: "; for(vector<int>::iterator it = q.begin(); it != q.end(); it++){ cout<< *it << " "; } cout<<endl; return 0; }

3、random_shuffle函数

用法与reverse相同。随机打乱。

#include<iostream> #include<algorithm> #include<vector> using namespace std; int main(){ vector<int> a; // 添加元素 a.push_back(1); a.push_back(2); a.push_back(3); a.push_back(4); a.push_back(5); // 输出 for(vector<int>::iterator it = a.begin(); it != a.end(); it++){ cout<< *it <<endl; } cout<<endl; // 随机打乱 random_shuffle(a.begin(), a.end()); // 输出 for(vector<int>::iterator it = a.begin(); it != a.end(); it++){ cout<< *it <<endl; } return 0; }

4、sort函数

对两个迭代器(或指针)指定的部分进行快速排序。默认是升序排列。

#include<iostream> #include<algorithm> using namespace std; int main(){ int a[10] = {1,2,3,2,1,4,3,2,1,10}; // 默认是升序排列 sort(a,a + 10); for(int i = 0; i < 10; i ++){ cout<<a[i]<<endl; } cout<<endl; // 这种是降序排列 sort(a,a + 10,greater<int>()); for(int i = 0; i < 10; i ++){ cout<<a[i]<<endl; } return 0; }

5、lower_bound/upper_bound 函数

  1. lower_bound的第三个参数传入一个元素x,在两个迭代器(指针)指定的部分上执行二分查找,返回指向第一个大于等于x的元素的位置的迭代器(指针)。

upper_bound的用法和lower_bound大致相同,唯一的区别是查找第一个大于x的元素。当然,两个迭代器(指针)指定的部分应该是提前排好序的。

#include<iostream> #include<vector> #include<algorithm> using namespace std; int main(){ int a[10] = {1,3,5,7,9,2,4,6,8,10}; // 排序 sort(a,a + 10); // 在已排序的数组中找到>=5的最小整数的下标 int i = lower_bound(a, a + 10, 5) - a; cout<<i<<endl; // 在已排序的数组中找到>5的最小整数的下标 int j = upper_bound(a, a + 10, 5) - a; cout<<j<<endl; return 0; }

Read more

C++ 继承入门(上):从基础概念定义到默认成员函数,吃透类复用的核心逻辑

C++ 继承入门(上):从基础概念定义到默认成员函数,吃透类复用的核心逻辑

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》 《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心 ✨未择之路,不须回头 已择之路,纵是荆棘遍野,亦作花海遨游 目录 前言 一. 继承的概念与定义   1、继承的核心概念   2、继承的定义格式   3、继承方式与成员访问权限 二. 基类与派生类的转换:子类对象能当父类用吗? 三. 继承中的作用域:同名成员会冲突吗?   1、变量隐藏   2、函数隐藏 四、派生类的默认成员函数:构造、拷贝、析构怎么写?   1、构造函数:先调用父类构造,再初始化子类成员   2、拷贝构造:先拷贝父类,再拷贝子类   3、 赋值重载:

By Ne0inhk
2024第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

2024第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

记录刷题的过程、感悟、题解。 希望能帮到,那些与我一同前行的,来自远方的朋友😉 大纲:  1、握手问题-(解析)-简单组合问题(别人叫她 鸽巢定理)😇,感觉叫高级了  2、小球反弹-(解析)-简单物理问题,不太容易想  3、好数-(解析)-简单运用分支计算  4、R 格式-(解析)-高精度,不是快速幂😉  5、宝石组合-(解析)-lcm推论(gcd、lcm结合)  6、数字接龙-(解析)-DFS(蓝桥专属、每年必有一道)  7、拔河-(解析)-定一端,动一端😎 题目: 1、握手问题 问题描述

By Ne0inhk
【C++笔记】STL详解:string的实现

【C++笔记】STL详解:string的实现

前言:                 在前面的学习中,我们已经初步掌握了string类接口函数的使用方法,本文将带领大家从零开始,逐步实现一个完整的string类。          一、string类总览                 温馨提示: 为了避免与标准库中的string产生命名冲突,我们使用mystd命名空间进行封装。 namespace mystd { class string { public: //迭代器 typedef char* iterator; typedef const char* const_iterator; //默认成员函数 string(); string(const char* str); //构造函数 string(const string& s); //拷贝构造函数 string& operator=(const string& s); //赋值运算符重载函数 ~string(); //析构函数 //迭代器相关函数 iterator begin(

By Ne0inhk