二叉树学习心得——个人笔记(例题Tree)

二叉树学习心得

首先构建一个二叉树

需要存储数据进去,可以使用一个结构体会更加的方便

顺便提一嘴,头文件是

#include
#include
struct node {
    int left, right;
};
node tree[MAXN];

其中 left 和 right 分别代表其左右子节点,读入也十分方便,

_for (i,1,n) cin>>tree[i].left>>tree[i].right

这里介绍一个for循环的简化写法,非常方便。

在头文件下放入新的定义

#define _for(i,a,b) for(int i=(a);i<=(b);i++)

以后便可以直接简写。

怎么将数据输入进二叉树

记得将第一项标记出来,就是头根标记出来,作为递归的起点

正所谓擒贼先擒王

可以先确定跟,然后再顺次输入左右树

cin>>t;
cin>>tree[t].left>>tree[t].right;

之后我们还需要知道如何遍历这颗二叉树

我们需要从根节点出发,先递归遍历该节点的左节点,再递归遍历该节点的右节点

dfs(tree[i].left,deep+1)
dfs(tree[i].right,deep+1)

中间可以加入其他操作,当到达叶子节点时就应该结束操作,直接return。

所以整个应该是

void dfs(int di,int deep)
{
    if (id==0) return ;//这个还可以是其他的限制条件,主要是底部什么时候是空,看题目
    ...//其他操作
    cout<

使用递归遍历它会自动遍历至底部

重点!!先序排列,中序排列,后序排列

这个先中后其实就是根所在的位置

先序排列 根左右

中序排列 左根右

后序排列 左右根

不难发现,先序排列的根一定在开头,后序排列的根一定在末尾,而中序排列的根会出现在中间

如此,当我们已知先序或后序和中序后,我们便可以求出未知的那项

具体方法是使用递归

1,先找出根(先序找开头,后序找结尾)

在这里可以用string函数来找开头和结尾,#.size()即可知道字符串长度,注意-1,因为是从0开始计数。

2,找到根所在的位置,将中序一分为二

这里可以使用substr(开头,结尾)也是非常好用

3, 先序就先右边再左边,因为先序是往右边开始

​ 后序就先左边再右边,因为后序要往左开始

void dfs(string in ,string after)
{
	if(in.size()>0)
	{
		ch = after[after.size()-1];
		cout<
void dfs(string in ,string after)
{
	if(in.size()>0)
	{
		ch = after[0];
		cout<
当已知中序排列和后序排列后,该如何构建二叉树呢?

这不同于知道根和各各子节点的位置,是需要通过中序遍历和后序遍历才可以构建的二叉树,方法和已知中序和后序求先序很相似,但也有不同

int create_tree(int inorder_start,int postorder_start,int length)
{
	if(length<=0){
		return 0;
	}
	int root = postorder[postorder_start+length-1];
	int count =0;
	while(inorder[inorder_start+count]!=root){
		count ++;
	}
	T_left[root]=create_tree(inorder_start,postorder_start,count);
	T_right[root]=create_tree(inorder_start+count+1,postorder_start+count,length-1-count);
	return root;
}
关键在于要将root存入左右从而达到建树的目的,最后要记得返回root,同时在编程时也碰到一些问题,例如
int root 和int count 一定要放在函数里面才可以。

如果需要求每个子节点的最小和,存在多路径最小的情况下,应该选择终端叶子节点上具有最小值的那条路径,且输出那个最小值的终端叶子

void findmin(int root,int sum)
{
	sum+=root;
	if(T_left[root]==0&&T_right[root]==0){
		if(sum0) findmin(T_left[root],sum);
	if(T_right[root]>0) findmin(T_right[root],sum);
}

写的非常清楚明白了

对我来说的难题

树 Tree

题面翻译

输入一个二叉树的中序和后序遍历,请你输出一个叶子节点,该叶子节点到根的数值总和最小,且这个叶子是编号最小的那个。
输入:
您的程序将从输入文件中读取两行(直到文件结尾)。第一行是树的中序遍历值序列,第二行是树的后序遍历值序列。所有值将不同,大于零且小于或等于10000.二叉树的节1<=N<=10000。
输出:
对于每个树描述,您应该输出最小值路径的叶节点的值。存在多路径最小的情况下,您应该选择终端叶子节点上具有最小值的那条路径,且输出那个最小值的终端叶子。

题目描述

PDF

二叉树学习心得——个人笔记(例题Tree)_第1张图片

输入格式

二叉树学习心得——个人笔记(例题Tree)_第2张图片

输出格式

样例 #1

样例输入 #1

3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
255

样例输出 #1

1
3
255
#include
using namespace std;

const int maxn = 10010;
int postorder[maxn],inorder[maxn],T_left[maxn],T_right[maxn],n,x;
int min_sum,min_root,sum,root;
string str,str2;

bool readline(int *arr)
{
	if(!getline(cin,str))
	{
		return false;
	}
	stringstream s(str);
	n=0,x;
	while (s>>x){
		arr[n++]=x;
		
	}
	return true;
}

int create_tree(int inorder_start,int postorder_start,int length)
{
	if(length<=0){
		return 0;
	}
	int root = postorder[postorder_start+length-1];
	int count =0;
	while(inorder[inorder_start+count]!=root){
		count ++;
	}
	T_left[root]=create_tree(inorder_start,postorder_start,count);
	T_right[root]=create_tree(inorder_start+count+1,postorder_start+count,length-1-count);
	return root;
}

//int create_tree(int inorder_start,int postorder_start,int length)
//{
//	if(length<=0){
//		return 0;
//	}
//	int root = postorder[length-1];
//	int count =0;
//	while(inorder[count]!=root){
//		count ++;
//	}
//	T_left[root]=create_tree(0,0,count);
//	T_right[root]=create_tree(count+1,count,length-1-count);
//	return root;
//}

void findmin(int root,int sum)
{
	sum+=root;
	if(T_left[root]==0&&T_right[root]==0){
		if(sum0) findmin(T_left[root],sum);
	if(T_right[root]>0) findmin(T_right[root],sum);
}

int main()
{
	while(readline(inorder)){
		readline(postorder);
		min_sum=0xfffffff,min_root=0xfffffff;
		create_tree(0,0,n);  
		findmin(postorder[n-1],0);
		cout<

你可能感兴趣的:(数据结构与算法,c++,深度优先,算法,1024程序员节)