在使用c++刷题的过程中,经常会碰到python顺手就来但是c++里面就是不会用的数据类型和数据结构,这里做一些总结
所有用到的数据类型结构包括但不限于:
整数,数组,字典,集合,字符串,小根堆
1、整数
整数没啥好说的,直接int a结束,但是要注意溢出的问题
2、数组
python中的数组非常简单,而且元素是可以通过append直接添加的,但是c++中的常规数组在定义的时候就要确定长度,除非使用vector或者new一个长度为a的数组,python中的列表更像是c++中的vector
// 使用new来创建动态数组
int len=8;
int*arr = new int[len];
// 使用vector来创建动态数组
int len=8;
// arr(len)注意是括号不是[],而且里面放的是长度
// 如果要全部初始化成0,可以这样: vector<int> arr(len,0);
vector<int> arr(len,0);
// 初始化为特定的值
for(int i=0;i<len;i++){
arr[i]=i;
}
// 直接遍历vector中的元素,类似于 for i in nums
for(int num:arr){
printf("%d\n",num);
}
// 对arr进行切片,类似于 b=a[x:y],左闭右开,下面的操作就是
// subarr=arr[0:4]
vector<int> subarr(arr.begin()+0,arr.begin()+4);
// 追加一个元素,即append
arr.push_back(8);
// 排序,即arr.sort(reverse=True),需要#include<algorithm>
// 最后一个参数greater<int>()用来降序,不写就是升序
sort(arr.begin(),arr.end(),greater<int>());
// 原生数组的使用
// 通过定义一个const变量来设置原生数组的长度
const int b_size=300;
int b[b_size];
// 成批初始化数组,注意memset需要#include<string.h>
// 特别注意,memset是按照字节操作的,所以3*sizeof(int)
// 是将b的前3个元素的每一个字节都设置为-1,由于-1的二进制是全为1
// 所以最终这三个元素都是-1,如果换成其他的数就不好使了,但是这3个数
// 仍然会是一样的,后面没有初始化的297个数是随机的
memset(b,-1,3*sizeof(int));
for(int i=0;i<4;i++)printf("b[%d]=%d\n",i,b[i]);
int a[7]={1,2,3,4,5,6,7};
// c++的原生数组没有size属性,不能直接得到,只能自己算出来
// 而且,一般用于循环遍历的变量类型是size_t,不是int,也不是unsigned int
size_t size=sizeof(a)/sizeof(a[0]);
for(size_t i=0;i<size;i++){
// 格式化输出时,size_t类型的变量有属于自己的格式占位符%u,表示无符号整数
printf("a[%u]=%d\n",i,a[i]);
}
}
3、字典
python中的字典dict中常用的是defaultdict,可以指定默认的值。
c++中的map对默认将键值对按照键升序排列,所以要看情况使用 unordered_map
map<int,int> mymap;
// 可以先判断这个键在不在里面,如果不在则刻意指定
if (mymap.find(1)==mymap.end()){
mymap[1]=10; // 添加元素和python一样
}
// 遍历字典
for(auto iter=mymap.begin();iter!=mymap.end();iter++){
printf("key=%d, value=%d\n",iter->first,iter->second);
}
// 查看map的大小
int size=mymap.size();
// 删除某个键值对,删除成功返回1,否则返回0
int state = mymap.erase(1);
// 清空整个字典
mymap.erase(mymap.begin(),mymap.end());
// 或者
mymap.clear();
4、集合
对于c++而言,集合 set是一个有序的集合,但是python中的set其实是一个无需的集合,对应于c++中的unordered_set
unordered_set<int> m_set;
// 添加元素
for(int i=0;i<10;i++){
m_set.insert(i);
}
// 查找元素
if(m_set.find(4)!=m_set.end()){
printf("元素%d在集合中\n",4);
}
// 删除指定的元素,成功返回1,否则返回0
int is_delete = m_set.erase(1);
还有一个非常重要的点是,unorder_set和set的使用范围不同,unorder_set使用哈希表实现,因此内部的元素一定要是可哈希的,但是与python不同,c++中的元素也没有hash函数,所以还不如使用vector来重载一下,因此这里定义一个新的类型MySet,MySet可以直接存储vector类型的数据
#include<unordered_set>
#include<tuple>
#include<iostream>
#include<vector>
using namespace std;
struct VectorHash {
size_t operator()(const std::vector<int>& v) const {
std::hash<int> hasher;
size_t seed = 0;
for (int i : v) {
seed ^= hasher(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
return seed;
}
};
using MySet = std::unordered_set<std::vector<int>, VectorHash>;
// 使用也很简单
int main(){
MySet mySet;
mySet.insert({1,2,3});
mySet.insert({3,2,1});
for(auto it:mySet){
cout<<it[0]<<' '<<it[1]<<' '<<it[2]<< endl;
}
return 0;
}
5、字符串
// 一定要以'\0'结尾
char s[]={'h','e','l','l','o','\0'};
// 这样就不需要以'\0'结尾
char s2[]="world";
printf("s=%s\n",s);
printf("s2=%s\n",s2);
// 查询长度strlen 需要包含头文件string.h
printf("s的长度是%d个字符\n", strlen(s));
printf("s的长度是%d个字符\n", strlen(s));
// 字符串的切片
string s3="myboy";
string sliceed = s3.substr(0,2);
// cout<<"字符串s[0:2]="<<sliceed<<endl;
// 注意,string是c++特有的类型,printf不能直接输出,需要转换.c_str()
printf("字符串s[0:2]=%s\n", sliceed.c_str());