二叉树(二)

原方法出自

http://blog.csdn.net/liaozelin_/article/details/78495589


LeetCode 105

二叉树(二)

题意:给出先序遍历和中序遍历的结果,求整棵树的原貌。

思路:1、前序遍历结果的第一个元素必是根节点

         2、在中序遍历结果中找到前序遍历的第一个元素,该元素的左侧为左子树集合,右侧为右子树集合。

         3、递归

#include "stdafx.h"
#include<iostream>
#include<vector>
using namespace std;

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

//函数声明
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder);
TreeNode* driver(vector<int>& preorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi);
int find(vector<int>& vec, int low, int high, int val);

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
	//调用函数返回完整的树
	return driver(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* driver(vector<int>& preorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi) {
	// 递归的边界,子树为空或着只有一个结点
	if (p_lo > p_hi) return NULL;
	if (p_lo == p_hi) return new TreeNode(preorder[p_lo]);
	//获取该节点的价值
	int node_val = preorder[p_lo];
	//获取该节点在中序遍历序列中的位置
	int index_in = find(inorder, i_lo, i_hi, node_val);
	//前序遍历序列中,该节点的左子树集合大小
	int pre_left_len = index_in - i_lo;
	TreeNode* node = new TreeNode(node_val);
	// preorder[p_lo+1 ... p_lo+pre_left_len]是先序数组中与现结点左子树对应的部分。
	// inorder[i_lo ... index_in-1]是中序数组中与现结点左子树对应的部分。
	node->left = driver(preorder, inorder, p_lo + 1, p_lo + pre_left_len, i_lo, index_in - 1);
	// preorder[ p_lo + pre_left_len + 1 ...  p_hi]是先序数组中与现结点右子树对应的部分。
	// inorder[index_in + 1 ...   i_hi]是中序数组中与现结点右子树对应的部分。
	node->right = driver(preorder, inorder, p_lo + pre_left_len + 1, p_hi, index_in + 1, i_hi);
	return node;
}

//找当前节点在中序遍历序列中的索引位置
int find(vector<int>& vec, int low, int high, int val) {
	for (int i = low; i <= high; ++i) {
		if (vec[i] == val) return i;
	}
	return -1;
}

int main()
{
	vector<int> preorder = { 3,9,20,15,7 };
	vector<int>inorder = { 9,3,15,20,7 };
	//vector<int>num = { 3,9,20,-1,-1,15,7 };
	//TreeNode* answer=CreatTree(num);
	TreeNode* answer = buildTree(preorder, inorder);

	return 0;
}




LeetCode  106

二叉树(二)

题意:给中序和后续遍历,求整棵树。

思路:后序遍历序列最后一个元素为根节点,找该点在前序遍历中的索引位置。该点在前序遍历中左侧为左子树集合,右侧为右子树集合。

#include "stdafx.h"
#include<iostream>
#include<vector>
using namespace std;

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

//函数声明
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder);
TreeNode* driver(vector<int>& preorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi);
int find(vector<int>& vec, int low, int high, int val);

TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
	return driver(postorder, inorder, 0, postorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* driver(vector<int>& postorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi) {
	if (p_lo > p_hi) return nullptr;
	if (p_lo == p_hi) return new TreeNode(postorder[p_hi]);
	//获取后序遍历序列最后一个元素的值
	int node_val = postorder[p_hi];
	//获取后序遍历最后一个元素在前序遍历序列中的索引位置
	int index_in =find(inorder, i_lo, i_hi, node_val);
	//该点的左子树集合大小为pre_left_len
	int pre_left_len = index_in - i_lo;
	TreeNode* node = new TreeNode(node_val);
	// preorder[p_lo ... p_lo + pre_left_len - 1]是中序数组中与现结点左子树对应的部分。
	// inorder[i_lo ... index_in - 1]是后续数组中与现结点左子树对应的部分。
	node->left = driver(postorder, inorder, p_lo, p_lo + pre_left_len - 1, i_lo, index_in - 1);
	// preorder[p_lo + pre_left_len ... p_hi - 1]是中序数组中与现结点左子树对应的部分。
	// inorder[index_in + 1 ... i_hi]是后续数组中与现结点左子树对应的部分。
	node->right = driver(postorder, inorder, p_lo + pre_left_len, p_hi - 1, index_in + 1, i_hi);
	return node;
}

int find(vector<int>& vec, int low, int high, int val) {
	for (int i = low; i <= high; ++i) {
		if (vec[i] == val) return i;
	}
	return -1;
}

int main()
{
	vector<int> preorder = { 9,3,15,20,7 };
	vector<int>inorder = { 9,15,7,20,3 };
	TreeNode* answer = buildTree(preorder, inorder);
	return 0;
}



LeetCode 129


二叉树(二)


深度遍历的题,不难,具体实现代码如下:

#include "stdafx.h"
#include<iostream>
#include<vector>
#include<queue> 
using namespace std;

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

//构造二叉树
TreeNode* CreatTree(vector<int>&nums) {
	size_t length = nums.size();
	if (length == 0) return nullptr;
	int index = 0;
	TreeNode* root = new TreeNode(nums[index]);
	index++;
	TreeNode* p = nullptr;
	queue<TreeNode*>trans;
	trans.push(root);
	while (!trans.empty() && index < length) {
		p = trans.front();
		trans.pop();
		if (index < length && nums[index] != -1) {
			TreeNode *LeftNode = new TreeNode(nums[index]);
			p->left = LeftNode;
			trans.push(LeftNode);
		}
		index++;
		if (index < length && nums[index] != -1) {
			TreeNode *RightNode = new TreeNode(nums[index]);
			p->right = RightNode;
			trans.push(RightNode);
		}
		index++;
	}
	return root;
}

//递归,将每一支路上的总和加到sum中。这里sum传引用,为了修改sum的值
void solve(TreeNode* root, int cur,int& sum) {
	if (!root)
		return;
	//当遍历到的节点是叶子结点时
	if (root->left == NULL && root->right == NULL) {
		cur = cur * 10 + root->val;
		sum += cur;
		return;
	}
	//非叶子结点,把之前累积的值乘以10与当前节点的值相加,传值到下一次递归
	solve(root->left, cur * 10 + root->val, sum);
	solve(root->right, cur * 10 + root->val, sum);
}

int sumNumbers(TreeNode* root) {
	//当root为空,说明树是空的
	if (!root)
		return 0;
	int sum = 0;
	solve(root, 0, sum);
	return sum;
}

int main()
{
	vector<int>nums = { 3,5,1,6,2,0,8,-1,-1,7,4,-1,-1,-1,-1 };
	TreeNode* root = CreatTree(nums);
	int answer = sumNumbers(root);
	return 0;
}


上一篇:c++读取和写入TXT文件的整理


下一篇:二叉树