首页 > 其他分享 >根据先序序列和中序序列构造二叉树

根据先序序列和中序序列构造二叉树

时间:2023-10-04 09:03:12浏览次数:43  
标签:左子 int 中序 右子 二叉树 l1 序列 先序

阅读本文之前希望读者可以先掌握如何根据先序序列和中序序列手动画出二叉树。
所用二叉树数据结构如下:

typedef struct TreeNode{
	char data;
	TreeNode *lchild,*rchild;
} TreeNode,*Tree;

该方法声明如下

Tree createTree(char *pre,int l1,int r1,char *in,int l2,int r2);

接下来先介绍每一个参数用途

  • char *pre :数组给出的先序序列
  • char *in :数组给出的中序序列
  • int l1:左子树的先序序列起始位置
  • int l2:右子树的先序序列起始位置
  • int r1:左子树先序序列的结束位置
  • int r2:右子树的先序序列的结束位置

接下来画图解释这六个参数
1696402315.jpg
简而言之,pre,in为两个序列,l1,r1为pre数组的边界符,l2,r2为in数组的边界符
以下给出我对于这个算法的大体实现思路
我们画图具体分析以下,首先,我拿到之后,肯定知道先序序列第一个节点就是根节点,我们可以在中序队列中遍历找到根节点的位置,如下图所示
1696402822.jpg
黄色为根节点,我用i去指向中序队列中的根节点,此时i左边的元素均为左子树上的元素,i右边的元素均为右子树上的元素。
我们可以使用i-l2来计算出左子树的元素个数,使用r2-i来计算出右子树的元素个数,分别记作Llen和Rlen
此时如果Llen小于等于0,说明左子树没有元素,我可以直接让左子树为空,Rlen小于等于0,说明右子树没有元素,我可以直接让右子树元素为空。
左子树和右子树为空的情况我们讨论完了,接下来考虑左右子树不为空的情况,如果左子树不为空,那么左子树的中序序列就是图中蓝色的部分,下标范围为[l2,i-1],而左子树的先序序列可以看到图中先序序列的蓝色部分,也就是[l1+1,l1+Llen],我们将其作为参数递归调用自身,就可以递归创建左子树。
右子树则是图中绿色的部分,右子树的中序序列为[i+1,r2],先序序列为[l1+Llen+1,r1],我们将其作为参数调用自身就可以实现递归创建右子树。
接下来给出具体实现:

#include <iostream>
using namespace std;
typedef struct TreeNode{
	char data;
	TreeNode *lchild,*rchild;
} TreeNode,*Tree;
void initNode(TreeNode *t){//初始化节点
	t -> lchild = NULL;
	t -> rchild = NULL;
}
TreeNode *createNode(char d){//创建一个节点
	TreeNode *p = new TreeNode;
	initNode(p);
	p -> data = d;
	return p;
}
Tree createTree(char *pre,int l1,int r1,char *in,int l2,int r2){
	//创建根节点
	char rootData = pre[l1];//先序遍历第一个节点必为根节点,取出根节点数据
	TreeNode *root = createNode(rootData);//创建根节点
	//找到根节点在中序遍历中的位置
	int i = l2;//记录根节点在中序遍历中的位置
	while(in[i] != rootData){
		i++;
	}
    //此时i指向中序序列中的根节点
	int Llen = i-l2;//计算左子树元素个数
	int Rlen = r2-i;//计算右子树元素个数
	//先序序列:左子树范围为[l1+1,l1+Llen]  右子树范围为[l1+Llen+1,r1]
	if(Llen <= 0){//如果左子树元素个数小于等于0
		root -> lchild = NULL;//左子树为空
	}else{
		//递归创建左子树
		root -> lchild = createTree(pre,l1+1,l1+Llen,in,l2,i-1);
	}
	if(Rlen <= 0){//如果右子树元素个数小于等于0
		root -> rchild = NULL;//右子树为空
	}else{
		//递归创建右子树
		root -> rchild = createTree(pre,l1+Llen+1,r1,in,i+1,r2);
	}
	return root;
}
//中序遍历
void inorder(Tree t){
	if(t){//如果t不为空
		inorder(t -> lchild);//左孩子
		cout << t -> data;
		inorder(t -> rchild);//右孩子
	}
}
//先序遍历
void preorder(Tree t){
	if(t){//如果t不为空
		cout << t -> data;
		preorder(t -> lchild);//左孩子
		preorder(t -> rchild);//右孩子
	}
}
int main(void){
	char pre[] = "DAEFBCHGI";
	char in[] = "EAFDHCBGI";
	Tree t = createTree(pre,0,8,in,0,8);
	inorder(t);
	cout << endl;
	preorder(t);
	return 0;
}

标签:左子,int,中序,右子,二叉树,l1,序列,先序
From: https://www.cnblogs.com/zhangyunling/p/17741901.html

相关文章

  • 题解 [CSP-S 2021] 括号序列
    题目链接对于括号题,基本是栈匹配没有匹配的左括号和区间\(dp\)两个方向。这道题括号序列并不确定,只能用区间\(dp\)搞。如果直接设\(f_{l,r}\)表示\(l\simr\)的合法括号序列,那么由区间\(dp\)的套路可知,需要枚举中间点进行合并,那么\(()()()\)的情况就会出问题,原因是......
  • 二叉树遍历(中序遍历)
    中序遍历,就是从最左边开始,把每个节点垂直投影到同一直线上,然后从左往右读值就可以了。口诀:先左再根再右......
  • 二叉树遍历(先序遍历)
    口诀:先根再左再右......
  • P1305 新二叉树
    Problem题目简述给你一个二叉树,求前序遍历。输入的方法为左右孩子表示法。思路这道题的话可以DFS。定义一个结构体\(node\),存储\(3\)个信息:\(fa,l,r\)分别表示父亲、左子树、右子树。然后下标就是字母的\(ACSII\)码。然后每次将左子树、右子树的\(fa\)更新,然后......
  • Prufer序列
    Prufer序列的转化方法见这篇博客(这篇文章里这道模板题的高精处理方法也看看)这里主要是对这篇博客的一些说明。首先:为什么Prufer序列与无根树一一对应?我们要先知道两个引理:出现在Prufer序列中的点一定是原无根树的非叶子节点,没有出现在Prufer序列中的一定是原无根树的叶子节点......
  • C 序列(seq)
    Day\(|\Sigma|\)。模拟赛里面的题,早上降智没调出来。题意大概就是求区间所有子区间的只出现在子区间内的数的最大值的和。记录一个数\(i\)的最左出现位置\(l_i\)和最右出现位置\(r_i\),一个数只在\([L,R]\)中出现当且仅当\([l_i,r_i]\subseteq[L,R]\)。考虑扫描线,统一......
  • 【洛谷 P1305】新二叉树 题解(结构体数组+先序遍历+二叉树)
    新二叉树题目描述输入一串二叉树,输出其前序遍历。输入格式第一行为二叉树的节点数。()后面行,每一个字母为节点,后两个字母分别为其左右儿子。特别地,数据保证第一行读入的节点必为根节点。空节点用*表示输出格式二叉树的前序遍历。样例#1样例输入#16abcbdicj*d**i**j**......
  • 给PG数据库已有表,已存在列添加序列并设置序列当前值为自增列的最大值
    CREATEORREPLACEFUNCTION"public"."add_sequence_to_table"("p_table_name"text,"p_column_name"text)RETURNS"pg_catalog"."void"AS$BODY$DECLAREmax_valueINTEGER;sequence_nametext;B......
  • Leetcode 1143. 最长公共子序列
    https://leetcode.cn/problems/longest-common-subsequence/description/?envType=study-plan-v2&envId=top-100-liked给定两个字符串text1和text2,返回这两个字符串的最长公共子序列的长度。如果不存在公共子序列,返回0。一个字符串的子序列是指这样一个新的字符串:它......
  • 《Java编程思想第四版》学习笔记32--关于static字段的序列化
    //:CADState.java//Savingandrestoringthestateofa//pretendCADsystem.importjava.io.*;importjava.util.*;abstractclassShapeimplementsSerializable{publicstaticfinalintRED=1,BLUE=2,GREEN=3;privateintxPos,yPos,dimension;p......