C++牛客网非核心代码模式

引言

牛客网刷题模式和leetcode的核心代码模式不同,其需要自行处理输入输出。本篇介绍刷题如何处理输入输出,以及刷题遇到的一些常见函数与其他知识。

以之前遇到的华为od的一道真题为例,处理输入输出:
二叉树层序遍历
题目描述
有一棵二叉树,每个节点由一个大写字母标识(最多26个节点)。
现有两组字母,分别表示后序遍历(左孩子->右孩子->父节点)和中序遍历(左孩子->父节点->右孩子)的结果,请你输出层序遍历的结果。

输入
每个输入文件一行,第一个字符串表示后序遍历结果,第二个字符串表示中序遍历结果。(每串只包含大写字母)
中间用单空格分隔。

输出
输出仅一行,表示层序遍历的结果,结尾换行。

示例1 输入输出示例仅供调试,后台判题数据一般不包含示例
输入
CBEFDA CBAEDF
输出
ABDCEF

#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
using namespace std;

struct Node
{
   
   
	Node *left;
	Node *right;
	int val;
	Node(int x) :val(x), left(nullptr), right(nullptr) {
   
   }
};

void SplitString(string input, vector<string> &ouput, string pattern)
{
   
   
	string::size_type pos;
	input += pattern;
	for (int i = 0; i < input.size(); i++)
	{
   
   
		pos = input.find(pattern, i);
		if (pos < input.size())
		{
   
   
			string temp = input.substr(i, pos - i);
			if (!(temp.empty()) && (temp != pattern))
			{
   
   
				ouput.push_back(temp);
			}
		}
		i = pos + pattern.size() - 1;
	}
}

Node *builTree(string backArray, string medArray)
{
   
   
	//如果后序序列为空(因为在不断删减)
	if (backArray.empty())
		return nullptr;
	//拿到后序的最后节点为根节点
	int head = backArray.back();
	//建立当前树的根节点
	Node *root = new Node(head);

	//在中序序列中找到该根节点的位置,进行分割左右
	int headIndex = medArray.find(head);
	//当根节点位置让左有节点,创建左子树(左子树长度都一样长)
	if (headIndex > 0)
	{
   
   
		root->left = builTree(backArray.substr(0, headIndex), medArray.substr(0, headIndex));
	}
	else
	{
   
   
		root->left = nullptr;
	}
	//如果有右子树
	if (headIndex < medArray.size() - 1)
	{
   
   						//注意每次后序序列都要除去尾节点(根节点),这里易错
		root->right = builTree(backArray.substr(headIndex).erase(backArray.substr(headIndex).size() - 1), medArray.substr(headIndex + 1));
	}
	else
	{
   
   
		root->right = nullptr;
	}

	return root;
}

int main()
{
   
   
	string s;
	getline(cin, s);
	//分割为后序中序遍历序列
	vector<string> treeArrays;
	SplitString(s, treeArrays, " ");
	//拿到后序中序序列
	string a = treeArrays[0];
	string b = treeArrays[1];

	//根据后序和中序序列构造出树
	Node *node = builTree(a,b);
	
	//进行层序遍历
	string tree;
	queue<Node *> Q;
	Q.push(node);
	while (!Q.empty())
	{
   
   
		Node *head = Q.front();
		Q.pop();
		tree.push_back(head->val);
		if (head->left != nullptr)	Q.push(head->left);
		if (head->right != nullptr)	Q.push(head->right);
	}
	cout << tree << endl;

	return 0;
}

1.字符串分割的几种常见处理方式

(1)输入输出

首先先回顾一下输出输出:
C++的输入输出通常使用cin、cout对象加上<< >>输入输出运算符。

①cin

cin是以空格、换行符为界(即不读入)来输入内容。
循环读入内容,并遇到换行符退出:

while (cin >> num) {
   
   
		nums.push_back(num);
		if (getchar() == '\n') break;
	}

②getline

cin每次遇到空格和换行符就会结束,那么如果不想结束,就要使用getline
getline能够读入空格与换行符,并且默认是以换行符结束的,所以这里存在一个陷阱:

如果在getline之前用了cin或getline,那么cin之后的输入的换行符会被getline读取,导致真正的内容无法读入。

getline(cin,str,a)是将str读入到cin流中,当a不写时默认遇到换行符停止输入,并将换行符丢弃,如果a写了,如a为‘#’则表示遇到‘#’停止读入。

while(getline(cin,line))语句注意这里默认回车符停止读入,按Ctrl+Z或键入EOF回车即可退出循环。在这个语句中,首先getline从标准输入设备上读入字符,然后返回给输入流cin,注意了,是cin,所以while判断语句的真实判断对象是cin,也就是判断当前是否存在有效的输入流。

原理:

cin.getline读取换行符并替换成’\0’,并且不会主动丢弃换行符,会把它留在输入队列中。

使用:
循环读入每一行,遇到空行结束

while (getline(cin, line) && line.compare("") != 0) {
   
   	//compare相等返回0,>返回1,<返回-1
		line += '\n';			//每输入完一行都换行
		file += line;			//将line放入file中
		line.clear();			//清空line为下次做准备
	}

解决方案就是清空输入缓冲区

③关于清空输入缓冲区

先补充一下C语言的输入
scanf:不会读入空格,Tab,换行符,遇到这些会输入结束。
gets:可以读入空格,Tab,换行符。
两者在读取字符串结束后会在末尾加’\0’

关于清空输入缓冲区,一般使用cin.ignore();
容易混淆的点:

cin.clear();是清理错误标识符而不是清空缓冲区。
当输入的类型不符合定义的变量类型时,会出现输入异常的情况 if (cin.fail()),那么如果输入错误,就要使用cin.clear()清理错误标识符,然后使用cin.ignore()取走刚才流中的字符来实现清空输入缓冲区。
感兴趣的可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值