机试复习-4

1.string类

string类型和数值的转换

※数值→字符串

to_string函数

//具体做法
int i=1234;
string g=to_string(i);//这样就转成字符串1234了
//下面就是字符串转为数字,类似下面还有stof,stoi,stod
string d = "1289347647";
int j = stoi(d);
cout << j;

string怎样输入输出呢?

如果用scanf就必须要转成字符数组之后再输入

好麻烦而且我一直错

http://t.csdnimg.cn/elFx7

1.字符个数※

/*
就是输入一行英文句子,统计出这一句的单词个数,字母个数,出现次数最多的字母个数
*/
#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
using namespace std;
//int slen(string a)
//{
//	int count = 0;
//	while()
//}
int main()
{	//如何统计单词个数?前一个字符是空格并且这一个不是,就++

	//先输入
	//string a;
	//cin >> a;//cin不是遇见空格就断吗
	//是的,不仅是cin还有scanf也是的,他们都是一次只能输入一个字符
	char arr[200] = { 0 };//定义字符数组
	fgets(arr, 200, stdin);//通过这样的方式去获取字符串
	int i = 0;
	//或者可以是cin.getline()
	//好,现在输入了
	//接下来先统计字母的个数
	int count1 = 0; int count2 = 0;//2是记录单词个数,1是记录字母个数
	bool isspace=true;//用来记录现在字符前面的一个字符
	map<char, int> alphamap;
	while (true)
	{
		if (arr[i] == '\0' || arr[i] == '\n')break;
		else if (arr[i] == ' ')
		{
			isspace = true;
		}
		else
		{
			count1++;
			if (isspace)count2++;
			//转换大小写
			if (arr[i] >= 'A' && arr[i] <= 'Z')arr[i] += 32;
			++alphamap[arr[i]];//这怎么这样?
			isspace = false;
		}
		i++;
	}
	cout << count1 << endl;
	cout << count2 << endl;

	//迭代器便利map
	map<char, int>::iterator it;//it->first指的是第一个;it->second指的是第二个,我们要比赛的是第二个
	int max = 0;
	for (it = alphamap.begin(); it != alphamap.end(); ++it)
	{
		if (it->second > max)max = it->second;
	}
	for (it = alphamap.begin(); it != alphamap.end(); it++)
	{
		if (it->second == max)cout << it->first<<' ';
	}
	cout << '\n';
	cout << max;

	//cout << "单词个数是" << count2 << endl;
	//cout << "字母个数是" << count1 << endl;
}

2.浮点数相加

/*描述
求2个浮点数相加的和 题目中输入输出中出现浮点数都有如下的形式:
P1P2...Pi.Q1Q2...Qj 
对于整数部分,P1P2...Pi是一个非负整数 
对于小数部分,Qj不等于0
输入描述:
对于每组案例,每组测试数据占2行,分别是两个加数。
输出描述:
每组案例是n行,每组测试数据有一行输出是相应的和。 
输出保证一定是一个小数部分不为0的浮点数*/
//经典高精度计算
//思路:和列竖式一样,先对齐:思路:提取小数,提取整数,把它们做成函数
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
string getint(string a)
{
	//char b=a[0];
	//int i = 0; int j = 0;
	//string c[200];
	//while (b != '.')
	//{
	//	c[j++] = a[i++];
	//	b = a[i];
	//}
	return a.substr(0, a.find('.'));//前面是起始位置,后面是长度
}
string getfraction(string a)//截取字符串的一部分;找到某个字符对应的下标
{
	return a.substr(a.find('.')+1, a.size() - a.find('.'));//!!!!!!!!!!!!!!!!!!!!!!!!
}
//使用引用参数,直接返回信息,不用写返回类型这样
void fplus(string& res, int& carry, string fa, string fb)
{
	//首先对齐
	int  size = max(fa.size(), fb.size());//字符串返回而这较大的size//!!!!!!!!!!!!!!!!!!
	while (fa.size() < size)//!!!!!!!!!!!!!!!!!!!!!!!
	{
		fa.push_back('0');
	}//!!!!!!!!!!!!!!!!!!!}
	while (fb.size() < size)

	{fb.push_back('0');}
	//开始运算
	//开辟空间
	res.resize(size);
	carry = 0;
	for (int i = size - 1; i >= 0; i--)
	{
		//从右往左便利
		//字符0和数字0怎样转换?字符0-‘0’
		if (fa[i] + fb[i] +carry- '0' > '9') {//感觉前面是数字呀?为啥和字符比呢
			res[i] = fa[i] + fb[i]+carry - '0' - 10;
			carry = 1;
		}
		else
		{
			res[i] = fa[i] + fb[i]+carry - '0';
			carry = 0;
		}
	}
	}
void iplus(string& res, int& carry, int carry1, string ia, string ib)
{
	/*int size = max(ia.size(), ib.size());
	while (ia.size() < size)ia.append('0');
	while (ib.size() < size)ib.push_back('0');
	res.resize(size);
	carry = 0;
	for (int i = size - 1; i >= 0; i -- )
	{
		if (i == size - 1)
		{
			if (ia[i] + ib[i] + carry +carry1- '0' > '9')
			{
				res[i] = ia[i] + ib[i] + carry - '0' - 10;
				carry = 1;
			}
			else
			{
				res[i] = ia[i] + ib[i] + carry - '0';
			}
		}
		else{
			if (ia[i] + ib[i] + carry - '0' > '9')
		{
			res[i] = ia[i] + ib[i] + carry - '0' - 10;
			carry = 1;
		}
		else
		{
			res[i] = ia[i] + ib[i] + carry - '0';
			carry = 0;
		}
		}

	}*/
	res.clear();
	for (int i = ia.size() - 1, j = ib.size() - 1; i >= 0 || j >= 0 || carry == 1; i--, j--)
	{
		if (i == ia.size() - 1 && j == ib.size()-1)
		{
			if (ia[i] + ib[j] + carry +carry1- '0' > '9')
			{
				//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
				res.insert(res.begin(), ia[i] + ib[j] + carry+carry1 - '0' - 10);
				carry = 1;
			}
			else
			{
				//res[i] = ia[i] + ib[i] + carry - '0';
				res.insert(res.begin(), ia[i] + ib[j] + carry +carry1- '0');
				carry = 0;
			}
		}
		else {
			if (i >= 0 && j >= 0)
			{
				if (ia[i] + ib[j] + carry - '0' > '9')
				{
					//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
					res.insert(res.begin(), ia[i] + ib[j] + carry - '0' - 10);
					carry = 1;
				}
				else
				{
					//res[i] = ia[i] + ib[i] + carry - '0';
					res.insert(res.begin(), ia[i] + ib[j] + carry - '0');
					carry = 0;
				}
			}
			else if (i >= 0 && j < 0)
			{
				if (ia[i] + carry > '9')
				{
					//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
					res.insert(res.begin(), ia[i] + carry - 10);
					carry = 1;
				}
				else
				{
					//res[i] = ia[i] + ib[i] + carry - '0';
					res.insert(res.begin(), ia[i] + carry);
					carry = 0;
				}
			}
			else if (i < 0 && j >= 0)
			{
				if (ib[j] + carry > '9')
				{
					//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
					res.insert(res.begin(), ib[j] + carry - 10);
					carry = 1;
				}
				else
				{
					//res[i] = ia[i] + ib[i] + carry - '0';
					res.insert(res.begin(), ib[j] + carry);
					carry = 0;
				}
			}
			else
			{
				res.insert(res.begin(), '1');
				carry = 0;
			}
		}
		}
		
}

int main()
{
	//string a = "12345.6789";
	//string b = "333.33333";
	string a; cin >> a;
	string b; cin >> b;
	string ia = getint(a);
	string ib = getint(b);
	string fa = getfraction(a);
	string fb = getfraction(b);
	//先计算小数,在计算整数
	string res; int carry;//分别是结果和进位
	fplus(res, carry, fa, fb);
	string res2;int carry2=0;
	iplus(res2, carry2, carry, ia, ib);
	cout << res2 << '.' << res << endl;

}

2.queue

操作受限的线性表

c++有现成的队列

#include<queue>
queue<int>myqueue;
队列支持:push,pop,front/back,emp

1.约瑟夫问题

思路:用一个for循环先搞一个队列,然后for循环把p-1个去掉,因为我们从第p个开始数,所以我们希望队头是第p个数;在用一个for循环循环n次,用来把这n个数都排出去;for循环内部,每次丢出去一个,先假装出去m-1个,然后队头留下真正出去的然后真正pop掉;

别忘了这个题是1~n,不是从0开始的

//n个小孩,从p开始报数,报m个,到m这个娃出去,直到全部出去
#include<iostream>
#include<queue>
#include<stdio.h>
using namespace std;
int main()
{
	//如何实现循环?pop后push即可
	int n, p, m;
	cin >> n >> p >> m;
	while (n !=0 ||p !=0|| m != 0)
	{
		int i;
		queue<int> cque;
		cque = queue<int>();
		for (i = 1; i <= n; i++)//题目从0开始的
		{
			cque.push(i);
		}//现在形成了一个队列
		for (i = 1; i <= p - 1; i++)//先把p-1个poppush走
		{
			cque.pop();
			cque.push(i);
		}//现在把p个都pop+push掉了,现在从队头数
		for (int j = 0; j < n;j++)//每一次都要把队列变为空,一次可以去掉一个,也可以是n次
		{
			//思路:队头才能出去→让m个成为对头
		//围成一圈→循环队列	
		//报数:出队,并转移到另一个队列中,结束之后另一个队列的队尾就是这次要删除的数据
		//如何实现循环?报数完之后加回来
			
			for (i = 1; i <=m-1 ; i++)//总之是叫m个数
			{
				int a = cque.front();//如何将新的数push进去
				cque.pop();
				cque.push(a);
			}
			cout << cque.front(); if (j != n - 1)cout << ',';
			cque.pop();
		}
		cout << '\n';
		cin >> n >> p >> m;
	}
}

3.stack

使用情况:有特权情况,深度优先遍历;表达式解析;递归
#include<stack>
stack<int> mystack;
操作:push(入栈);pop(出栈);top(栈顶元素);empty(判空)。

1.编排字符串

思路:就是栈,用两个栈来进行重复取元素操作

for循环输入m个字符;总体就是先输出,边输出边进入另一个栈,全部输出之后在从另一个栈导过来;

在第一次导入另一个站的过程中输出,两种情况,一种是小于4,那就全部输出,另一种是大于4,只输出4个,剩下的也要导进去,初始栈空了以后,在全部导进来,进行下一次

#include<stdio.h>
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
	//先输入//准备一个栈,站内元素是string类型,共m个元素
	int m; cin >> m;
	stack<string> mstack1;
	stack<string> mstack2;
	string a; int i, j; string b;
	for (i = 1; i <= m; i++)
	{
		cin >> a;
		mstack1.push(a);
		//现在栈内有几个元素,就输出他们,但是只能假装输出,如何假装输出?
		//准备两个栈,一个弹出来之后全部探进另一个,输出结束之后在全部弹回来
		//还要和4比较大小
		if (i <= 4)//随便输出
		{
			for(j=1;j<=i;j++)
			{
				b = mstack1.top();
				cout << j << '=' << b<<' ';
				mstack2.push(b);
				mstack1.pop();
			}//这样下来,1里面空了,2里面都是
		}
		else
		{
			for (j = 1; j <= 4; j++)
			{
				b = mstack1.top();
				cout << j << '=' << b<<' ';
				mstack2.push(b);
				mstack1.pop();
			}//现在mstack2里面还没要够,如何把剩下的也弄到2里,继续弹出1
			for (j = 5; j <= i; j++)
			{
				b = mstack1.top();
				mstack2.push(b);
				mstack1.pop();
			}
		}
		//所有的输出结束了,在这里弹回去
		for (j = 1; j <= i; j++)
		{
			b = mstack2.top();
			mstack1.push(b);
			mstack2.pop();
		}
		cout << '\n';
	}
}

2.括号匹配:
 

//输入一串括号,判断是否匹配,匹配就返回true
#include<stdio.h>
#include<iostream>
#include<stack>
#include<string>
using namespace std;
bool match(char a, char b)
{
	if (a == '<' && b == '>' || a == '{' && b == '}' || a == '(' && b == ')' || a == '[' && b == ']')
		return true;
	else
		return false;
}
int main()
{
	//错因:①错误的几种情况没说全:不匹配;到右括号时候栈空;最终栈内还有元素
	//②每次no之后都要return,避免no两次


	//先输入
	string a;
	cin >> a;
	int b = a.size(); int i;
	//思路:碰到左括号就入栈,一直入栈,直到遇到右括号,
	//碰到右括号与栈顶元素相比较,匹配就弹出来
	stack<char> mstack; char c;
	for (i = 0; i < b; i++)
	{
		if (a[i] == '<' || a[i] == '(' || a[i] == '{' || a[i] == '[')
		{
			mstack.push(a[i]);
		}
		if (a[i] == '>' || a[i] == ')' || a[i] == '}' || a[i] == ']')
		{
			
			if (empty(mstack)) {
				cout << "no";
				return 0;
			}c = mstack.top();
			if (match(c,a[i]))mstack.pop();
			else 
			{
				cout << "no";
				return 0;
			}
		}
	}
	if (!(empty(mstack))) {
		cout << "no";
		return 0;
	}
	if (i == b)cout << "yes";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值