【非递归版】洛谷P2171题解

题目链接

1 重要变量定义说明

1.1 node类型和a数组;

创建了node类型的变量,并开了node类型的数组。因为n的范围是3×10^5,比较大,所以解题策略是按照输入顺序存储,下标从1开始,每个元素的left和right初始化为0。之后通过比较节点val的大小,left存储该节点左孩子的数组下标,right存储右孩子的数组下标。

struct node{
	int val;
	int left;
	int right;
	node(){ }
	node(int v,int l,int r):val(v),left(l),right(r){ }
}a[300010]; 

样例数据按照上述方式的存储如下:

下标12345678
val1439103527
left03700000
right24056000

1.2 dm

存储树的深度

1.3 栈stk

本题使用非递归的方式实现后续遍历,从根节点开始,用栈存储后序遍历还没输出的节点的下标。

1.4 vis数组

用非递归后序遍历时,要避免a数组的元素多次入栈的问题,因此用vis数组标记元素是否入过栈。

2 二叉搜索树的构建

void build(){
	int dm=1,v;
	for(int i=1;i<=n;i++){
		cin>>v;
		a[i] = node(v,0,0);
		int j=1;
		if(i!=1){
			j=1;
			int d=2;
			while(1){
				if(a[j].val<a[i].val){
					if(a[j].right!=0){
						j=a[j].right;
						d++;	
					} 
					else{
						a[j].right = i;
						break;
					}
				}
				else if(a[j].val>a[i].val){
					if(a[j].left!=0){
						j=a[j].left;
						d++;
					} 
					else{
						a[j].left = i; 
						break;
					}
				}
			}
			dm = max(dm,d);
		} 
	}
	cout<<"deep="<<dm<<endl;
}

3 二叉树的后序遍历

后序遍历是左-右-根,入栈顺序是根-右-左(因为栈是后进先出),当节点没有左孩子和右孩子时,就输出栈顶节点的值,并让该节点出栈,一直做直到栈空为止。

void traverse(){
	stack<int> stk;
	stk.push(1);
	vis[1]=1;
	int tp = stk.top();
	while(stk.empty()==0){
		tp = stk.top();
		bool ps=0; 
		if(a[tp].right!=0&&vis[a[tp].right]==0){
			stk.push(a[tp].right);
			vis[a[tp].right]=1; 
			ps=1; 
		}
		if(a[tp].left!=0&&vis[a[tp].left]==0){
			stk.push(a[tp].left);
			vis[a[tp].left]=1;
			ps=1;
		}	
		if(ps==0){
			cout<<a[tp].val<<endl;
			stk.pop();
		}
	}
}

4 AC代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	int val;
	int left;
	int right;
	node(){ }
	node(int v,int l,int r):val(v),left(l),right(r){ }
}a[300010]; 
bool vis[300010];
int n;
void build(){
	int dm=1,v;
	for(int i=1;i<=n;i++){
		cin>>v;
		a[i] = node(v,0,0);
		int j=1;
		if(i!=1){
			j=1;
			int d=2;
			while(1){
				if(a[j].val<a[i].val){
					if(a[j].right!=0){
						j=a[j].right;
						d++;	
					} 
					else{
						a[j].right = i;
						break;
					}
				}
				else if(a[j].val>a[i].val){
					if(a[j].left!=0){
						j=a[j].left;
						d++;
					} 
					else{
						a[j].left = i; 
						break;
					}
				}
			}
			dm = max(dm,d);
		} 
	}
	cout<<"deep="<<dm<<endl;
}

void traverse(){
	stack<int> stk;
	stk.push(1);
	vis[1]=1;
	int tp = stk.top();
	while(stk.empty()==0){
		tp = stk.top();
		bool ps=0; 
		if(a[tp].right!=0&&vis[a[tp].right]==0){
			stk.push(a[tp].right);
			vis[a[tp].right]=1; 
			ps=1; 
		}
		if(a[tp].left!=0&&vis[a[tp].left]==0){
			stk.push(a[tp].left);
			vis[a[tp].left]=1;
			ps=1;
		}	
		if(ps==0){
			cout<<a[tp].val<<endl;
			stk.pop();
		}
	}
}
int main(){
	cin>>n;
	build();
	traverse();	
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值