第三十一篇,C++面经之手写代码(五)

这一篇先写个二叉树的题目,二叉树也是面试中常考到的算法与数据结构的知识点。

一、二叉树的生成与层序遍历

这一篇写个从#include从main开始的完整代码。
首先stNode定义了二叉树的节点结构,即存储一个数据,指向左右子节点。
func()是输出不分层的实现方法,即层序遍历后把整个树一层层展开、接续,串行地存储到一个std::vector中;levelOrder()是输出分层的实现方法,按树的原有层次存储遍历的结果,使用了一层嵌套的std::vector结构。
gen()是二叉树生成算法,用了递归,输入n是树的层数,cur是当前该生成第几层了,root是第cur层的上层父节点,即cur层生成的是root的左右子节点;main()函数中调用gen()生成了一个5层的完全二叉树,并用func()做了一次输出不分层的层序遍历,感兴趣的朋友可以拿levelOrder()看看输出分层的结果。

#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <future>

//二叉树生成、层序遍历(仅遍历,输出不分层)
#include <queue>
using namespace std;

struct stNode
{
	stNode(int n) : num(n), left(nullptr), right(nullptr) {}
	int num;
	stNode* left;
	stNode* right;
};
//
// 层序遍历,输出不分层
void func(stNode* root, std::vector<int>& tmpVector)
{
	std::queue<stNode*> tmpQueue;
	if (root == nullptr)
		return;

	tmpQueue.push(root);
	while (tmpQueue.size() > 0)
	{
		stNode* tmp = tmpQueue.front();
		tmpVector.push_back(tmp->num);

		if (tmp->left != nullptr)
			tmpQueue.push(tmp->left);
		if (tmp->right != nullptr)
			tmpQueue.push(tmp->right);

		tmpQueue.pop();
	}
}
// 
// 输出分层 
std::vector<std::vector<int>> levelOrder(TreeNode* root)
{
	// write code here
	std::vector<std::vector<int>> res;
	
	if (!root) return res;
	
	std::queue<TreeNode*> qu;
	qu.push(root);
	while (!qu.empty())
	{
		int size = qu.size();
		std::vector<int> vec;
		while (size--)
		{
			TreeNode* node = qu.front();
			qu.pop();
			vec.push_back(node->val);
			if (node->left) qu.push(node->left);
			if (node->right) qu.push(node->right);
		}
		if (vec.size() > 0) res.push_back(vec);
	}
	return res;
}

void gen(int n, int cur, stNode* root)
{
	if (cur <= n)
	{
		root->left = new stNode(root->num * 2);
		root->right = new stNode(root->num * 2 + 1);
		gen(n, cur + 1, root->left);
		gen(n, cur + 1, root->right);
	}
}

int main()
{
	stNode* root1 = new stNode(1);
	int datum = 2;
	gen(5, 2, root1);

	std::vector<int> res;
	func(root1, res);
	for (auto a : res)
		std::cout << a << std::endl;
	return 0;
}

在输出不分层方法func()中,也仅是输出结构展开成一维,元素的先后顺序还是要遵循原有的层级及左右顺序,考虑到这一层隐含约束,采用先入先出的队列结构std::queue作为中转比较合适,从root层开始,每个节点先将自己加入队列,然后加入其左右子节点,将queue的队首弹出并push进vector中;如此循环往复,直到queue为空即可。
在输出分层方法levelOrder()中,queue的作用和不分层方法中一样,只不过入队出队的控制有所区别。因为输出要分层,所以对树的每一层都保存一个vector,同时对queue的size做精细控制与使用,获取size时总是表征当前层中节点的个数,如此便能向每层的vector中完整地保存该层节点的遍历结果;每遍历完一层,将本层vectorpush进外层vector;如此循环往复,即可实现输出分层的层序遍历,且保留同一层中各节点的左右先后顺序。

二、输出整数的各个位上的数字

比如数字703,依次将百位的7、十位的0、个位的3输出,不考虑正负,这是一个典型的除与模的计算。
倒序输出如下,输出的依次是3、0、7,这是最简单的做法:

void func(unsigned int number)
{
    do
    {
        std::cout << number % 10 << std::endl;
    } while ((number /= 10) != 0);
}

正序输出,见有的用一边scanf一边printf的,这种纯属取巧而且万一直接给你个完整数字呢?还有用数组或者vector存放每一位的,但显然也不是最优解,最优解应当是要求不用缓存。代码如下:

void func(unsigned int number)
{
    unsigned int pow = 1, tmp = number;
    while ((tmp /= 10) != 0)
    {
        pow *= 10;
    }
    
    do
    {
        std::cout << number / pow << std::endl;
        number %= pow;
        pow /= 10;
    } while (pow != 0);
}

先把最高位找出来,是10的多少次方,存到pow里,然后倒着逐步往个位找,这里注意,尤其第二个while的控制条件,要防止出现中间如果有哪一位是0的时候不输出的bug。

三、翻转一个数字

接上一题,把数字反转输出,比如输入723,输出327,需要考虑正负,比如输入-723,输出-327。
在上一题倒序输出的基础上,代码如下:

void func(int number)
{
    if (number < 0)
    {
        std::cout << "-";
        number = abs(number);
    }
    do
    {
        std::cout << number % 10;
    } while ((number /= 10) != 0);
}

四、判断一个点是否在三角形中

参考叉乘法海伦公式法,重点是求三角形面积。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值