1.知识补充延拓
一:printf的一个特性。
我们发现,把包括小数点在内的5个字符顺序反转后输出即可。进而我们联想到 printf
函数的一个重要特性:参数从后往前求值。 即:
printf("%u %u\n", work1(), work2())
会先执行 work2()
再执行 work1()
。
输入123.4可以得到4.321。(因为:","运算符正常来讲使从左往右计算的,但函数中作为参数的分隔符,它是从右往左来读入参数的。)
#include<iostream>
#include<string>
using namespace std;
int main()
{
printf("%c%c%c%c%c", getchar(), getchar(), getchar(), getchar(), getchar());
}
二:ceil()函数是向上取整的函数,floor()函数是向下取整的函数。
向上取整:1.01---2。向下取整:1.01---1.
三:位运算
位运算是计算机中的一种基本运算,它对二进制数进行操作。常见的位运算有按位与(&)、按位或(|)、按位异或(^)
-
按位与(&):对应位都为1时,结果为1,否则为0。数学上的且。
int a = 1;
int b = 1;
int c = a & b; // 结果为 1
int a = 1;
int b = 0;
int c = a & b; // 结果为 0
2.按位或(|):对应位有一个为1时,结果为1,否则为0。数学上的或。
int a = 1;
int b = 0;
int c = a | b;//结果是1
3.按位异或(^):对应位不同则结果为1,相同则结果为0。
int a = 1;
int b = 0;
int c = a ^ b; //结果为1
四:sort()排序
sort()排序是指将一个数组按从小到大排序,可用于字符数组等等方面。例如:
1.字符数组排序:
#include <iostream>
#include <algorithm>
#include <string>
int main() {
std::string str = "hello world";
std::sort(str.begin(), str.end());
std::cout << "排序后的字符串: " << str << std::endl;
return 0;//结果为排序后的字符串: dehllloorw
}
值得注意的是,这个排序是按ASCII排序的,空格的ASCII是32,是最小的。
2.一般数组的排序
1.二维数组
#include <iostream>
#include <vector>
#include <algorithm>
bool compare(const std::vector<int>& a, const std::vector<int>& b) {
if (a[0] == b[0]) {
return a[1] < b[1];
}
return a[0] < b[0];
}
int main() {
std::vector<std::vector<int>> arr = {{3, 2}, {1, 4}, {5, 6}};
std::sort(arr.begin(), arr.end(), compare);
for (const auto& row : arr) {
for (int num : row) {
std::cout << num << " ";
}
std::cout << std::endl;
}
return 0;
}
这是结果,这个排序的顺序是按照每个子数组的第一个元素进行升序排序,如果第一个元素相同,则按照第二个元素进行升序排序。
1 4
3 2
5 6
2.一维数组
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> numbers = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
std::sort(numbers.begin(), numbers.end());
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}
输出结果:
1 1 2 3 3 4 5 5 5 6 9
3.sort排序的姊妹分支:quick_sort()
快速排序(quick_sort)是一种高效的排序算法,其优点包括:
- 时间复杂度为O(nlogn),在大多数情况下比其它排序算法更快。
- 原地排序,不需要额外的存储空间。
- 对于部分有序的数组,快速排序的性能表现很好。
- 可以递归实现,代码简洁易懂。
- 是常用的排序算法之一,被广泛应用在各种领域
五:reverse()排序
将一个数组内的元素反向输出。
1.一般数组
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 5, 2, 3, 4};
std::reverse(vec.begin(), vec.end());
for (const auto& num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
结果为
4 3 2 5 1
2.字符数组
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<char> arr = {'g', 'e', 'e', 'k', 's'};
std::reverse(arr.begin(), arr.end());
for (const auto& c : arr) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
结果为
s k e e g
六:数字和字符串的相互转化
1.数字转换字符串to_string()
#include <iostream>
#include <string>
int main() {
int num = 123;
std::string str_num = std::to_string(num);
std::cout << "转换后的字符串为: " << str_num << std::endl;
return 0;
}
结果为123,利用这种想法我们可以将数字转换为字符串并运用相应的排序方法达到题目要求
2.字符串转换数字stoi()
#include <iostream>
#include <string>
int main() {
std::string str = "123";
int num = std::stoi(str);
std::cout << "转换后的数字为: " << num << std::endl;
return 0;
}
结果同理
数组名是一个常量。
七:指针
1.概念:通俗地说,指针就是内存中一个最小单元的编号,也就是地址。在程序运行时,所有的数据都是存放在内存中的,每个内存单元都有一个唯一的编号即内存地址。
2.指针和指针变量:指针变量说到底还是一个变量,变量的值就是分配给该变量的内存位置所储存的数值。
#include<bits/stdc++.h>
int main()
{
int a=32;
double b=3.14;
int* c=&a;
double* d=&b;
std::cout<<*c<<" "<<d;
}
-
辨析1.“int”表示指针所指向的数据类型是整型,“*”表示这是一个指针变量,“c”是你自己定义的变量名。
-
辨析2.c中存储的是a的地址,并不是a的值,d同理。而cout输出d时输出的结果是b的地址,而*c是输出的a的值。结果如下
32 0xe1b0bff870
理解:可以把指针变量看成一个监控器(int* c),监控器记录的是某一个地方(就是a的地址);而输出中的*c就相当于用眼睛观看(a是指向整型的指针)监控器内的画面。(*就像一个眼睛)因为监控器里的画面和现实画面一样(即输出*c的值和a的值一样),只要我不去看监控的内容,我就只知道那个监控是监控哪个地方的。(即输出带不带*号得到的是不同的值)。(输出中的*就是解引用操作)
八:字符数组常用函数
2.string的成员函数npos表示字符串中不存在子串的位置。它的类型为std::size_t,通常被赋值为字符串的长度。
std::string str = "hello world";
std::size_t pos = str.find("goodbye");
if (pos == std::string::npos) {
// 子串"goodbye"不存在于字符串str中
} else {
// 子串"goodbye"存在于字符串str中,位置为pos
}
3.find函数
4.查重并删:unique和erase
5..back()
6.char* str="hello world!";这个语句等价于一个含有该字符串的字符数组。
九:容器(要访问一个容器的元素需要迭代器或者相应的遍历算法)
1.vector
注意事项:vector需要头文件#include<vector>
2.vector的专属迭代器
注意事项:vector<int>::iterator
3.怎么定义vector容器
重点:vector<int> it;(定义一个名为it的存储int类型的vector容器)
4.怎么储存或添加数据
可以用stl里的东西:it.push_back(这里填数据);例如:
using namespace std;
vector<int> v;
v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);
//表示存入10 20 30 40
5.怎么遍历输出vector的元素(共三种方法,一二种方法是for循环)
方法一:表达式分开放
#include<bits/stdc++.h>
#include<vector>
int main()
{
using namespace std;
vector<int> v;
v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);
vector<int>::iterator vbegin=v.begin();
vector<int>::iterator vend=v.end();
for(vector<int>::iterator vibegin;vbegin!=vend;vbegin++){
cout<<*vbegin<<endl;
}
return 0;
}
方法二: 所有的表达式放一块
#include<bits/stdc++.h>
#include<vector>
int main()
{
using namespace std;
vector<int> v;
v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);
for(vector<int>::iterator it=v.begin();it!=v.end();it++)
cout<<*it<<endl;
return 0;
}
方法三:利用遍历算法for_each()
#include<bits/stdc++.h>
#include<vector>
void print(int cmp)
{
std::cout<<cmp<<std::endl;
}
int main()
{
using namespace std;
vector<int> v;
v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);
for_each(v.begin(),v.end(),print);
return 0;
}
遍历算法解析:for_each()有三个参数,第一个是需要遍历的数组的首元素,第二个是末尾元素的后一位,第三个是一个回调函数。也就是说第一个参数是某个vector的成员函数.begin(),另一个是.end(),最后一个是回调函数的函数名称。
注意:for_each()和for作用是一样的,但是前者的运行时间更短。vector就理解为一个数组,尖括号内就是元素类型,it是数组内元素的地址,begin end返回地址
如何遍历二维数组:
#include<bits/stdc++.h>
#include<vector>
int main()
{
using namespace std;
vector<vector<int>> v;
vector<int> v1;
vector<int> v2;
vector<int> v3;
vector<int> v4;
for(int i=0;i<4;i++){
v1.push_back(i+1);
v2.push_back(i+2);
v3.push_back(i+3);
v4.push_back(i+4);
}
for(vector<vector<int>>::iterator it =v.begin();it!=v.end();it++)
{
//原来应该是直接cout<<*it;但是这里是嵌套容器
for(vector<int>::iterator vit=(*it).begin();vit!=(*it).end();vit++)
{
//这里的*vit相当于v1,v2,v3,v4中的元素
cout<<*vit<<" ";
}
cout<<endl;
}
return 0;
}
find是第一次出现的位置,rfind是最后一次出现的位置
rfind和find结合使用可以判断字符串中是否有唯一的字符,get
2.珍藏题系列
1.P5710 【深基3.例2】数的性质![](https://i-blog.csdnimg.cn/blog_migrate/5664cb6c0aad6c5773100bcafc283b58.png)
方案一:
我们可以写出判断是否满足条件的两个函数:
int a(int x) {return !(x%2);}
int b(int x) {return x>4&&x<=12;}
小A想要两个都满足 ⇒⇒ a(x)&b(x)=1;
Uim想要至少一个满足 ⇒⇒ a(x)|b(x)=1;
八尾勇想要刚好一个满足 ⇒⇒ a(x)^b(x)=1;
正妹想要两个都不满足 ⇒⇒ !a(x)&!b(x)=1.
由于符合想要的就输出1,不符合想要的就输出 0,那我们直接输出表达式的值就好了,后面可以不判断是否等于1.
#include<cstdio>
using namespace std;
int x;
int a(int x) {return !(x%2);}//判断第一个条件
int b(int x) {return x>4&&x<=12;} //判断第二个条件
int main()
{
scanf("%d",&x);//输入
printf("%d %d %d %d",a(x)&b(x),a(x)|b(x),a(x)^b(x),!a(x)&!b(x));//分别判断
return 0;
} //结束awa