文章目录
计算程序运行的时间
#include<iostream>
#include<windows.h>
using namespace std;
int main{
cout << "消耗的时间是:" << endl;
DWORD time_start = GetTickCount(); //从操作系统启动经过的毫秒数
/*
你需要调用的程序!
*/
DWORD time_end = GetTickCount();
cout << (time_end - time_start) << "ms\n ";
}
数组之间的操作
两个new出来的数组相互复制
使用memcpy函数
#include<cstring>
int main(){
memcpy(b,a,sizeof(a));
}
void *memcpy(void *dst, void *src, size_t size);
- 将src上的,大小为size字节的数据复制到dst上
- 需要引入头文件cstring
将数据写入和写出到txt文件中
将数据写入到txt文件中
#include<fstream>
//打开文件的读写
ofstream fout("path.txt");
fout << "test" << endl;
fout.close();
- 注意:
- 如果要在函数也能实现将数据写入到txrt文件中,要将文件流对象声明为全局变量,即再全局打开
- 如果main函数中打开,就只能再main函数中进行读写
深度遍历的一般形式
- 递归终止条件中的操作:用来对已经完全的递归体进行调整和判定的
void dfs(int layer){
//递归终止条件,一般是到达最后一层或者是最后一层的下面一层
if(layer >= buttom){
/*
这里可以对已经形成的最终的递归结果进行整体的调整和判断
*/
return;
}else{
//没有到达最底层,水平方向上的遍历顺序
for (int i = start; i < end; ++i)
{
//注意,这里的numArray是全局变量,是所有的递归函数都可以引用的
numArray[layer] = i;
//约束函数,满足约束函数可以进一步向下进行递归
//注意:约束函数可以在递归的过程中,对中间变量进行调整
// 在他还没有到达最终状态的时候进行调整
if(constraint(layer)){
dfs(layer+1)
}
}
}
}
实现对结构体某一项项目的排序
# include<algorithm>
//定义物品结构体
struct Item
{
//物品编号
int ItemID;
//物品价值
int value;
//物品重量
int weight;
// 价值除以重量
int ratio;
};
//定义物品结构体
Item *items = new Item[n];
//初始化结构体数组
for (int i = 0; i < n; i++)
{
items[i].ItemID = i;
items[i].value = v[i];
items[i].weight = w[i];
items[i].ratio = 1.0*v[i] / w[i];
}
//注意,这里需要对比较函数进行重载,
bool Itemcmp(Item item1, Item item2){
return item1.ratio > item2.ratio;
}
//按价值率排序
sort(items, items + n, Itemcmp);
优先队列的使用priority_queue队列的使用
- 自定义数据中的优先级,让优先级的高的队列优先出队
- 优先队列中具有队列的所有的特性,在其基础上添加了要给内部的排序
- 定义过程
//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;
//greater和less是std实现的两个仿函数
//greater是小顶堆
//less是大顶堆
//(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator()
//这个类就有了类似函数的行为,就是一个仿函数类了)
- 参数说明:
- Type是数据类型
- Container是容器类型:默认使用vector
- Functional,比较的方式
- 自定义比较类型:
#include <iostream>
#include <queue>
using namespace std;
//方法1
struct tmp1 //运算符重载<
{
int x;
tmp1(int a) {x = a;}
bool operator<(const tmp1& a) const
{
return x < a.x; //大顶堆
}
};
//方法2
struct tmp2 //重写仿函数
{
bool operator() (tmp1 a, tmp1 b)
{
return a.x < b.x; //大顶堆
}
};
int main()
{
tmp1 a(1);
tmp1 b(2);
tmp1 c(3);
priority_queue<tmp1> d;
d.push(b);
d.push(c);
d.push(a);
while (!d.empty())
{
cout << d.top().x << '\n';
d.pop();
}
cout << endl;
priority_queue<tmp1, vector<tmp1>, tmp2> f;
f.push(c);
f.push(b);
f.push(a);
while (!f.empty())
{
cout << f.top().x << '\n';
f.pop();
}
}
随机数的使用
rand()
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
cout <<"RAND_MAX:"<< RAND_MAX << endl;
for (int i = 0; i < 5; i++)
cout << rand() << endl;
}
- 在头文件cstdlib中
- 上限的定义在cstdlib头文件中,RAND_MAX中
- 产生的是伪随机数,每次执行的结果是相同
srand()
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
int main()
{
cout <<"RAND_MAX:"<< RAND_MAX << endl;
srand((unsigned)time(NULL));
for (int i = 0; i < 5; i++)
cout << rand() << endl;
}
- srand()初始化随机数发生器,根据传入的seed进行生成,同样在头文件cstdlib中
- 常用的time.h中的time函数,根据时间随机化种子,然后随机出不同的随机数
生成特定范围内的随机数
-
产生[a,b)的随机数,可以使用 (rand() % (b-a))+a;
-
产生[a,b]的随机数,可以使用 (rand() % (b-a+1))+a;
-
产生(a,b]的随机数,可以使用 (rand() % (b-a))+a+1;
-
建议使用srand进行随机
读取特定格式输入,并将数据提取出来保存到的vector中
使用strtok对函数进行隐形的分割
char str[80] = "-1,2,1,-4";
const char s[2] = ",";
char *token;
/* 获取第一个子字符串 */
token = strtok(str, s);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
printf( "%s\n", token );
cout<<"str的变化:"<<str<<endl;
cout<<"s的变化:"<<s<<endl;
token = strtok(NULL, s);
}
- 注意这个函数是比较奇怪的,会修改原来的字符串,而且第二次调用会使用原来的隐含调用,所以第二次在调用要设定第一个指针为NULL
- 其返回的是指向切割之后的token的指针
具体代码
int main(int argc, char const *argv[])
{
//定义一个vector变量
vector<int> nums;
string a = "";
getline(cin,a);
//去除开头和末尾的括号
a = a.erase(0,1);
a = a.erase(a.size()-1,1);
//讲string转成c中的cstring,用来进一步运算
char* str = new char(a.size()+1);
strcpy(str,a.c_str());
char* delima = ",";
//将之转为char*,调用strtok函数
char* p = strtok(str,delima);
while(p){
nums.push_back(atoi(p));
//cout<<atoi(p)<<endl;
p = strtok(NULL,delima);
}
//输出验证对应的vector是否成功
for (int i = 0; i < nums.size(); ++i) {
cout<<"final result is :"<<nums.at(i)<<endl;
}
return 0;
}
每次这里都挺耗费时间,想都想好了,输入输出搞了半天
使用sstream实现将字符串分割,将结果保存到vector中
//定义一个vector变量
vector<int> nums;
string a = "";
getline(cin,a);
//去除开头和末尾的括号
a = a.erase(0,1);
a = a.erase(a.size()-1,1);
stringstream sstr(a);
string token;
while(getline(sstr,token,',')){
cout<<token<<endl;
}
- 输出的结果:这个可太简单了,而且还好用
三种输入getchar()、get()和getline()的讲解
getchar()
- 从标准输入输出stdin中获取下一个字符,或者专门用来读取文件的末尾的EOF符号
- 具体说明:
- 从缓冲区中读走一个字符(清除缓冲区中一个字符)。
- 常用来读取缓冲区中的‘\n’换行符,scanf遇到换行符就会停止,但是不会读取换行符。
循环读取缓冲区中的char型数组,知道遇到了‘\n’换行符
char c;
while ((c=getchar())!='\n')
{
std::cout << c;
}
- 循环读取输入缓冲区的内容,直到遇到了换行符
cin的使用
- 输入特定类型的某一个数据
- 接收指定类型的数据,遇“空格”、“TAB”、“回车”都结束
type a;
cin>>a;
get的使用
- 使用get(变量名)接收字符
char ch;
ch = cin.get();
或者
cin.get(ch);
- 接收一行字符串,包括空格
char a[20];
cin.get(a,20);
cin.get(字符数组名,接收字符数目)
- 无参数,用来舍弃输入流中不需要的字符,或者舍弃回车
cin.get();
getline()
- 接受一个字符串,并接受空格输出,但是末尾会自动补上‘\0’,你要求读入5个,实际上会读取4个,最后一个默认会补上’\0’
char m[20];
cin.getline(m,5);
cout<<m<<endl;
- 如果什么都不加,没有任何字符限制,默认是读取完整的一个字符串
string a;
getline(cin,a);
- getline还有一个第三个参数,就是终止符,遇到终止符停止读取
- 注意,这个可以用来实现对字符串的按标志位区分
stringstream sstr(a);
string token;
while(getline(sstr,token,',')){
cout<<token<<endl;
}
auto关键字的使用
使用情况
- 声明变量时根据初始化表达式自动推断该变量的类型
使用样例
- 将类型冗长复杂,变量适用范围专一时,是程序更能清晰易读
std::vector<int> vect;
for(auto it = vect.begin(); it != vect.end(); ++it)
{ //it的类型是std::vector<int>::iterator
std::cin >> *it;
}
- 使用在for循环中,结合mapping使用
vector<string> mappings = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}, ans;
vector<string> letterCombinations(string digits) {
if(digits == "") return ans; // no combinations formed without any digits
helper(digits, 0, "");
return ans;
}
// recursive helper function
void helper(string &digits, int i, string combi){
if(i == size(digits)) { // base condition - push when we have recursed for all digits
ans.push_back(combi);
return;
}
// add and recurse for each character (chosen from current digit-charcter mapping)
for(auto &c : mappings[digits[i] - '2'])
helper(digits, i + 1, combi + c);
}