二叉树的基本操作(含遍历算法非递归实现全收录)

建立一颗二叉树(不要用数组),求二叉树的前序遍历序列,中序遍历序列,后序遍历序列,层序遍历序列,输出叶子数,和树的高度(根节点为第1层),实现二叉树查找

程序以下图为例:



输出样例:

preorder:
1 2 4 5 8 9 3 6 7
1 2 4 5 8 9 3 6 7


inorder:
4 2 8 5 9 1 6 3 7
4 2 8 5 9 1 6 3 7


postorder:
4 8 9 5 2 6 7 3 1
4 8 9 5 2 6 7 3 1


levelorder:
1 2 3 4 5 6 7 8 9


leavescount:
5


height:
4


8 is found

递归算法都挺好理解关键讲讲非递归遍历算法


前序和中序的非递归算法其实就是按照这个图走迷宫,经过非叶节点3次(只记录前两次),叶节点两次,前序遍历是第一次碰到就把节点输出出来,中序是第二次碰到再输出出来,怎么控制碰到的次数呢?用栈来控制,入栈表示当前第一次经过这个的节点,出栈,表示第二次经过这个节点。


而后序的非递归就有点麻烦了,它的入口和出口与前序中序的是反的,路径不变,如果第一次遇到就打印的的话打印出来的序列正好是后序的逆序,所以第一次遇到时可以先把它存在另一个栈里,最后再全部出栈即可得到正确的后序序列

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

typedef struct btnode* pt;

queue<pt>  q;
stack <pt> s,st;
int flag=0;
struct btnode
{
	int data;
	pt left,right;
};
pt init(int data)//初始化 
{
	pt tmp=new(struct btnode);
	tmp->data=data;
	tmp->left=tmp->right=NULL;
	return tmp;
}
pt maketree()//笨笨的建树方法,可以通过递归或数组建树,这里只是为了举例子 
{	
	pt root=init(1);
	pt tmp1=init(2);
	root->left=tmp1;
	pt tmp2=init(3);
	root->right=tmp2;
	pt tmp3=init(4);
	tmp1->left=tmp3;
	pt tmp4=init(5);
	tmp1->right=tmp4;
	pt tmp5=init(6);
	tmp2->left=tmp5;
	pt tmp6=init(7);
	tmp2->right=tmp6;
	pt tmp7=init(8);
	tmp4->left=tmp7;
	pt tmp8=init(9);
	tmp4->right=tmp8;
	return root;
}

void preorder(pt p)//先序的递归算法 
{
	if(p)
	{
		cout<<p->data<<" ";
		preorder(p->left);
		preorder(p->right);
	}
}


void preorder2(pt p)//前序非递归算法 
{
	if(p)
	{
		pt tmp;
		tmp=p;
		while(!s.empty()||tmp)//注意两个条件 
		{
			while(tmp)//控制回溯 
			{
				s.push(tmp);//第一次遇到 
				cout<<tmp->data<<" ";//第一次遇到直接打印 
				tmp=tmp->left;//按路径继续向左走 ,左孩子为空时回溯 
			}
			if(!s.empty())//控制回溯 
			{
				tmp=s.top();
				s.pop();//第二次遇到 
				tmp=tmp->right;//按路径向右走,右孩子为空时回溯 
			}
		}		
	}
}
	
void inorder(pt p)//中序递归算法 
{
	if(p)
	{
		inorder(p->left);
		cout<<p->data<<" ";
		inorder(p->right);
	}
}


void inorder2(pt p)//中序非递归算法 
{
	if(p)
	{
		pt tmp;
		tmp=p;
		while(!s.empty()||tmp)
		{
			while(tmp)
			{
				s.push(tmp);
				tmp=tmp->left;
			}
			if(!s.empty())
			{
				tmp=s.top();
				s.pop();
				cout<<tmp->data<<" ";//第二遇到打印 
				tmp=tmp->right;
			}
		}		
	}
}
void postorder(pt p)//后续递归算法 
{
	if(p)
	{
		postorder(p->left);
		postorder(p->right);
		cout<<p->data<<" ";
	}
}



void postorder2(pt p)//后序非递归算法 
{
	if(p)
	{
		pt tmp;
		tmp=p;
		while(!s.empty()||tmp)
		{
			while(tmp)
			{
				s.push(tmp);
				st.push(tmp);//第一次遇到时放入另一个栈中 
				tmp=tmp->right;//按路径向右走,右孩子为空时回溯 
			}
			if(!s.empty())
			{
				tmp=s.top();
				s.pop();
				tmp=tmp->left;//按路径继续向左走 ,左孩子为空时回溯 
			}
		}
		while(!st.empty())//打印后序序列 
		{
			tmp=st.top();
			st.pop();
			cout<<tmp->data<<" ";
		}
	}
}



void levelorder(pt p)//层序遍历 
{
	q.push(p);
	while(!q.empty())
	{
		pt tmp=q.front();
		if(tmp->left)
			q.push(tmp->left);
		if(tmp->right)
			q.push(tmp->right);
		cout<<tmp->data<<" ";
		q.pop();
	}
}

int countleaves(pt root)//数叶子数 
{
	if(!root)
		return 0;
	if(!root->left&&!root->right)
		return 1;
	return countleaves(root->left)+countleaves(root->right);
}
 int height(pt root)//求数的高度 
 {
 	if(!root)
 		return 0;
 	if(!root->right&&!root->left)
 		return 1;
 	return (height(root->left)>height(root->right)?height(root->left):height(root->right))+1;
}

	
void search(pt root,int x)//搜索点是否存在 
{
	if(root)
	{
		if(root->data==x)
		{
			flag=1;
			cout<<x<<" is found"<<endl;
		}
		if(!flag)
		{
			search(root->left,x);
			search(root->right,x);
		}
	}
}



int main()
{
	pt root=maketree();
	cout<<"preorder:"<<endl;
	preorder(root);
	cout<<endl;
	preorder2(root);
	cout<<endl<<endl;
	cout<<"inorder:"<<endl;
	inorder(root);
	cout<<endl;
	inorder2(root);
	cout<<endl<<endl;
	cout<<"postorder:"<<endl;
	postorder(root);
	cout<<endl;
	postorder2(root);
	cout<<endl<<endl;
	cout<<"levelorder:"<<endl;
	levelorder(root);
	cout<<endl<<endl;
	cout<<"leavescount:"<<endl;
	cout<<countleaves(root)<<endl<<endl;
	cout<<"height:"<<endl;
	cout<<height(root)<<endl<<endl;
	flag=0;
	search(root,8);
	cout<<endl;
	return 0;
}

前序和后序遍历非递归的另一个版本,不再讲解,有兴趣的朋友可以看一下


void preorder3(pt p)//先序遍历 
{
	if(p)
	{
		pt tmp;
		s.push(p);
		while(!s.empty())
		{
			tmp=s.top();
			cout<<tmp->data<<" ";
			s.pop();
			if(tmp->right)
				s.push(tmp->right);
			if(tmp->left)
				s.push(tmp->left);
		}	
	}
}




void postorder3(pt p)//后序遍历 
{
	pt tmp;
	s.push(p);
	while(!s.empty())
	{
		tmp=s.top();
		s.pop();
		st.push(tmp);
		if(tmp->left)
			s.push(tmp->left);
		if(tmp->right)
			s.push(tmp->right);
	}
	while(!st.empty())
	{
		tmp=st.top();
		st.pop();
		cout<<tmp->data<<" ";
	}
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值