遍历二叉树——华科

题目描述

在这里插入图片描述

知识点

二叉树的建立、二叉树的遍历

结果

在这里插入图片描述

实现

码前思考

  1. 这种题目我之前做了无数遍了,但是这次我再次做的时候还是有很多不太清楚的地方,这🧠它不管用呀。。。
  2. 我参照《算法笔记》上的写法,使用递归的方式来建树,递归函数的意义是获得前序遍历区间 [preL,preR]中序遍历区间 [inL,inR] 所在的树的根结点。递归的边界就是当前的树是空树,也就是preL>preR,或者inL > inR(两者是等价的)。
  3. 注意,前序遍历,后序遍历,层序遍历是用于获取根结点的,而中序遍历是用于划分左右子树的!所以必须要有中序遍历,但是对于BST来说它是不需要中序遍历的,因为它自身的性质已经决定了左右子树在哪了。

代码实现

//数组下标从1开始好理解一些 
#include "bits/stdc++.h"
using namespace std;

const int maxn = 30; 

//共享数据结构要注意初始化 
char pre[maxn];
char in[maxn]; 

struct node{
	char data;
	node* lchild;
	node* rchild;
}; 

//封装建立一个结点的函数 
node* newNode(char x){
	node* Node = new node;
	
	Node->data = x;
	Node->lchild = NULL;
	Node->rchild = NULL;
	
	return Node;
}

//递归建树函数
node* create(int preL,int preR,int inL,int inR){
	//如果该子树的大小小于等于0,说明是一棵空树 
	if(preL > preR){
		return NULL;
	}
	
	int k;
	//我们来寻找根结点 
	for(k=inL; k<=inR; k++){
		if(in[k] == pre[preL]){
			break;
		} 
	}
	
	node* root = new node;
	root->data = in[k];
	
	//开始创建左子树和右子树
	int numLeft = k - inL;
	root->lchild = create(preL+1,preL+numLeft,inL,k-1);
	root->rchild = create(preL+numLeft+1,preR,k+1,inR);
	
	return root; 
} 

void postOrder(node* root){
	if(root == NULL){
		return;
	}
	
	postOrder(root->lchild);
	postOrder(root->rchild);
	printf("%c",root->data);
} 

int main(){
	while(~(scanf("%s",pre+1))){
		//从数组下标1开始 
		scanf("%s",in+1);
		
		//收集长度
		int preL = 1;
		int preR = strlen(pre+1);
		int inL = 1;
		int inR = strlen(in+1);
		
		//初始化一个空的根结点
		node* root = NULL;
		
		//开始递归建树
		root = create(preL,preR,inL,inR); 
		
		//进行后序遍历
		postOrder(root);
		
		printf("\n"); 
	}
	return 0;
} 

码后反思

  1. 递归函数的意义很重要,一定要理清递归函数的意义,即这个函数是用来干什么的,它的输入是什么,它的输出是什么,不能瞎写,瞎写很容易写错,函数使用意义的,一定要好好思考函数的意义!这里我就一开始忽视了 create 函数的意义了。
  2. 如果是给的后序遍历结果和中序遍历结果我们怎么写?
    我们始终要记得后序遍历是为了提供根节点的,那么我们想想对于一个后序遍历序列,它的根结点在哪?没错,就是最后面。这样理清了思路,我们就可以依葫芦画瓢了。
  3. 在这里,我使用的是动态二叉链表实现二叉树,可能要涉及到内存的回收什么的。《王道》上面使用的是静态二叉链表,关于静态二叉链表可以看这里.
  4. 牛客上面还有更加简短的代码,它就没有建树了,我没仔细看,我先多题一解吧,一题多解后面再想。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值