二叉树(构建二叉树,知道先序遍历和中序遍历(或者中序遍历和后序遍历)求另外两种遍历)

目录

1.定义二叉树

2.根据题目给出的数据构建二叉树 

3.四种遍历

4.释放空间

5.加上主函数


1.定义二叉树

//定义二叉树的节点 
struct node{
	int val;        //节点的值
	node *left;     //定义左孩子
	node *right;    //定义右孩子
	node(int x):val(x),left(NULL),right(NULL){}  //在建立新的节点时使指针为空,下边的写法也可以
	//node(int val=0,node *left=NULL,node*right=NULL):val(val),left(left),right(right){}
};

2.根据题目给出的数据构建二叉树 

(1)知道先序遍历和中序遍历,构建树

void buildtree(int l,int r,int &t,node *&root){
	int flag=-1;//判断是否遍历完先序啥
	for(int i=l;i<=r;i++){//先序中的第一个数是根,所以引用的t是从1开始的,找到对应的中序的位置 
		if((in[i]==per[t])) {
			flag=i;break;//找到了就跳出循环-->建立新的节点 
		}
	}
	if(flag==-1) return;//结束
	root=new node(in[flag]);//新建节点 
	t++;//前序变成下一个节点
	//从(l,flag-1)在父节点的左侧建树(因为已知根节点,在中序中,在此根节点的左侧的点都在左子树上),flag+/-1是为了避开第一个父节点 ,右子树同理
	if(flag>l) buildtree(l,flag-1,t,root->left);//l是数据的左端r是数据的右端,t是先序遍历中根节点的下标 
	if(flag<r) buildtree(flag+1,r,t,root->right); 

}

(2)知道后序遍历和中序遍历,构建树

void build(int l,int r,int &t,node *&root){//t应该是后序的最后一位(应用的t应该是n),然后从后向前遍历(因为后序遍历的最后一个数是根节点)
	int flag=-1;//!!
	for(int i=l;i<=r;i++) //中序不需要管遍历顺序吧
		if(in[i]==post[t]){
			flag=i;break; 
		}
	if(flag==-1) return ;
	//
	root=new node(in[flag]);
	//
	t--;与上一个代码的不同
	/知道中序和后序,先递归右子树;;;知道先序和中序,先递归左子树 
	if(flag<r) build(flag+1,r,t,root->right);
	if(flag>l) build(l,flag-1,t,root->left);
	
} 

3.四种遍历

(1)先序遍历

void qian(node*root){
	if(root!=NULL){
		per[k++]=root->val;//输入根节点的值,per[]中按顺序输入先序遍历过的根节点的值
		qian(root->l);     //递归左子树
		qian(root->r);     //递归右子树
	}
}

(2)中序遍历

void zhong(node*root){
	if(root!=NULL){
		zhong(root->l);
        in[k++]=root->val;//in[]中是按中序遍历的根节点
		zhong(root->r);
	}
}

(3)后序遍历

void hou(node*root){
	if(root!=NULL){
		hou(root->l);
		hou(root->r);
        post[k++]=root->val;//post[]中是按后序遍历的根节点
	}
}

(4)层序遍历

用到queue:其想法就是从最上层的根节点开始,将其加入到队列中,然后输出,在删除这个元素(因为此函数传入的是根节点的地址T,所以在队列中加入或者删除元素不会改变传入的地址),并且判断这个根节点是否还有左右孩子,如果有就先让左孩子加入到队列中,再让右孩子,当根节点不再有孩子,队列为空时,无需再向下找

void  level(node *T,int n){//传入的n是为了控制空格的输出,只要求两个数之间有空格,最后一位数后边没有空格
	//node*
	queue<node*>queue;//队列命名为了queue!!!!其类型一定是node*(前往不要忘记*)
	queue.push(T);//根节点放入队列
	while(!queue.empty()){//如果队列不为空,下面三部走
		//1.
		T=queue.front();//对头元素出队,指针重新指向,front.()是将返回头元素但不删除 
		printf("%d",T->val);//父节点出队后,将左右孩子放入队列;
		if(n!=1) cout<<" ";
		n--;
		queue.pop();//删除队首元素 
		//2.
		if(T->left!=NULL)
			queue.push(T->left);//如果首元素的左子树不是空,将其左子树放入队列
			//入对的是一个地址元素
		//3.
		if(T->right!=NULL)
			queue.push(T->right); 
	} 
	
}

4.释放空间

void re_free(node *root){
	if(root==NULL) return ;
	re_free(root->left);
	re_free(root->right);
	delete root;
} 

5.加上主函数

(1)知道先序遍历和中序遍历得到后序遍历

  (2)   知道中序遍历和后序遍历得到前序遍历

(3)知道中序遍历和后序遍历得到层序遍历(天梯赛真题:树的遍历)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值