【数据结构】二叉树的简单操作及简单应用

前端之家收集整理的这篇文章主要介绍了【数据结构】二叉树的简单操作及简单应用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

简介:

二叉树的应用十分广泛。根据二叉树的前序序列和中序序列,可以构造出二叉树。构造方法可以采用递归和非递归。二叉树的遍历通常有四种方法,分别是前序遍历,中序遍历,后序遍历,层序遍历。其中,前序,中序,后序又有递归和非递归两种写法。求最近公共祖先的方法同样有很多。这里选择了一种时间、空间复杂度较低的方法

本文主要分为以下几个部分:

  1. 递归与非递归建树

  2. 不同方式的遍历

  3. 寻找最近公共父节点

正文:

  1. 建树

    1. 递归

每次搜到中序序列中当前节点的位置,以此位置为界,将中序序列中的区间一分为二,然后分别传给左、右子树进行递归。

    1. 非递归

栈中存储当前节点的子树区间(LR)以及他们的父节点(即当前节点)。

每次循环,将栈顶元素出栈,先找到当前元素在中序序列中的位置,然后根据对应的区间,将左右子树的区间入栈。

直到栈空为止。

注意:

应该先让右子树入栈,再让左子树入栈,保证顺序的正确。



  1. 遍历

    1. 递归

递归遍历比较简单,在每一层分别递归访问左子树右子树,然后根据前序,中序,后序的不同,调整输出语句的位置即可。



    1. 非递归

非递归主要是用栈实现,根据遍历顺序的不同,实现方法有所不同。

      1. 前序

每次访问栈顶元素,先把栈顶元素输出并弹出,然后将左右子树分别入栈,直到栈空为止。

注意先让右子树进栈,再让左子树进栈,保证输出顺序的正确。



      1. 中序

每次访问栈顶元素,先判断是否满足输出条件:是否是叶子节点、是否是已经访问过的父节点。满足则输出、弹出。

不满足则弹出栈顶(父节点),右子树入栈,原栈顶(即父节点)入栈,左子树入栈。

直到栈空为止。


      1. 后序

如果在前序遍历中,访问完父节点后,先访问右子树,在访问左子树,得到的序列正是后续访问的逆序列。

所以用一个数组储存按上述方法遍历得到的序列,最后逆向输出即可。


    1. 层序

利用队列,访问到队头元素,把它的左右子树放到对位,直到队列为空。



  1. 寻找最近公共父节点

建一个长度大于树的高度的数组,用来存储由根到目标节点的各个节点的访问情况。

然后从任一个目标节点开始向上访问,直到根节点,一路上所有的节点都标记位“已访问”。这样,已经标记过的便是此节点的父节点之一。

最后从另一个目标节点开始向上访问,一直到找到已经访问过的节点,此节点既是此节点的父节点,又是第一个节点的父节点,因此是两个节点的公共父节点。又因为第一个出现,所以是两个节点的最近公共祖先。

空间复杂度 :小于树的高度。

时间复杂度:小于2*树的高度。

CODE:

#include<iostream>
#define N n+1
using namespace std;
typedef struct Tree
{
	int data;
	int father,lson,rson;
};
Tree *T;
int n;
int *preord;	//存放前序表达序列 
int *midord;	//存放中序表达序列 
int now;		//递归所用计数器 

void find(int f1,int f2);	//【042-073】 寻找最近公共祖先(实现函数) 
void lca();					//【074-085】 寻找最近公共祖先(主函数) 

void oudlr1(int n);			//【086-092】 前序递归 
void oudlr2();				//【093-115】 前序非递归 
void ouldr1(int n);			//【116-122】 中序递归 
void ouldr2();				//【123-161】 中序非递归 
void oulrd1(int n);			//【162-168】 后序递归 
void oulrd2();				//【169-194】 后序非递归 
void floor();				//【195-207】 层序 
void putit(int head);		//【208-251】 输出函数 

int make1(int l,int r);		//【252-289】 递归建树 
void make2();				//【290-351】 非递归建树 
void build();				//【352-366】 建树总菜单 

void init(int n,int ord[]);	//【367-371】 输入序列 
void start();				//【372-388】 开始函数 

int main()
{
	start();
	build();
	putit(1);
	lca();
	return 0;
}
void find(int f1,int f2)
{
	int bo[N];
	int ff1,ff2;
	T[1].father=1;
	for (int i=0;i<=n;i++)
	{
	if (T[i].data==f1)
	{
		ff1=i;
	}
	if (T[i].data==f2)
	{
		ff2=i;
	}
	}
	for (int i=0;i<=n;i++)
	{
		bo[i]=0;
	}
	while (ff1!=1)
	{
		bo[ff1]=1;
		ff1=T[ff1].father;
	}
	while (bo[T[ff2].father]==0 && ff2!=1)
	{
		ff2=T[ff2].father;
	}
	cout<<"lca:"<<T[T[ff2].father].data<<endl;
	
}
void lca()
{
	int f1,f2;
	cout<<endl<<endl<<"输入要查找的两个节点,0 0 结束"<<endl;
	cin>>f1>>f2;
	while (!(f1==f2&&f1==0))
	{
		find(f1,f2);
		cin>>f1>>f2;
	}
	return;
}
void oudlr1(int n)		
{
	cout<<T[n].data<<" ";
	if (T[n].lson!=-1) oudlr1(T[n].lson);
	if (T[n].rson!=-1) oudlr1(T[n].rson);
	return;
}
void oudlr2()     
{
	int sta[N];
	int noww=1;
	sta[noww]=1;
	while (noww>0)
	{
		int stn=sta[noww];
		noww--;
		cout<<T[stn].data<<" ";
		if (T[stn].rson!=-1) 
		{
			noww++;
			sta[noww]=T[stn].rson;
		}
		if (T[stn].lson!=-1)
		{
			noww++;
			sta[noww]=T[stn].lson;
		}
	}
	return;
}
void ouldr1(int n)
{
	if (T[n].lson!=-1) ouldr1(T[n].lson);
	cout<<T[n].data<<" ";
	if (T[n].rson!=-1) ouldr1(T[n].rson);
	return;
}
void ouldr2()
{
	int boo[N];
	int sta[N];
	int now=1;
	sta[1]=1;
	for (int i=0;i<N;i++) boo[i]=0;
	while (now>0)
	{
		if (boo[sta[now]]==1)
		{
			cout<<T[sta[now]].data<<" ";
			now--;
			continue;
		}
		
		boo[sta[now]]=1;
		int nn=sta[now];
		if (T[nn].lson==-1 && T[nn].rson==-1)
		{
			cout<<T[nn].data<<" ";
			now--;
			continue;
		}
		if (T[nn].rson!=-1)
		{
			sta[now]=T[nn].rson;
			now++;
			sta[now]=nn;
		}
	    nn=sta[now];
		if (T[nn].lson!=-1)
		{
			now++;
			sta[now]=T[nn].lson;
		}
	}
	return;
}
void oulrd1(int n)
{
	if (T[n].lson!=-1) oulrd1(T[n].lson);
	if (T[n].rson!=-1) oulrd1(T[n].rson);
	cout<<T[n].data<<" ";
	return;
}
void oulrd2()
{
	int sta[N];
	int sta1[N];
	int noww=1,s=1;
	sta[noww]=1;
	while (noww>0)
	{
		int stn=sta[noww];
		noww--;
		sta1[s++]=T[stn].data;
		if (T[stn].lson!=-1)
		{
			noww++;
			sta[noww]=T[stn].lson;
		}
		if (T[stn].rson!=-1) 
		{
			noww++;
			sta[noww]=T[stn].rson;
		}
	}
	for (int i=0;i<n;i++)
	cout<<sta1[n-i]<<" ";
	return;
}
void floor()
{
	int que[N];
	int l=1,r=2;
	que[1]=1;
	while ((l<=r)&& (l<N))
	{
		if(T[que[l]].lson!=-1) que[r++]=T[que[l]].lson;
		if(T[que[l]].rson!=-1) que[r++]=T[que[l]].rson;	
		cout<<T[que[l]].data<<" ";
		l++;
	}
}
void putit(int head)
{
	cout<<endl<<"选择遍历方式:1、前序 2、中序 3、后序 4、层序"<<endl;
	int choose;
	cin>>choose;
	if (choose==1)
	{
	cout<<endl<<"前序遍历:"<<endl;
	cout<<"选择递归(0)非递归(1)"<<endl;
	int ch;
	cin>>ch;
	if (ch==0)
		oudlr1(head);
	else
		oudlr2();
	}
	else if (choose==2)
	{
	cout<<endl<<"中序遍历:"<<endl;
	cout<<"选择递归(0)非递归(1)"<<endl;
	int ch;
	cin>>ch;
	if (ch==0)
		ouldr1(head);
	else
		ouldr2();
	}
	else if (choose==3)
	{
	cout<<endl<<"后序遍历:"<<endl;
	cout<<"选择递归(0)非递归(0)"<<endl;
	int ch;
	cin>>ch;
	if (ch==0)
		oulrd1(head);
	else
		oulrd2();
	}
	else if (choose==4)
	{
	cout<<endl<<"层序遍历:"<<endl; 
	floor();
	}
}
int make1(int l,int r)
{
	int noww=now;
	T[noww].data=preord[now];
	if (l==r)
	{
		T[noww].lson=T[noww].rson=-1;
		return noww;
	}
	int mid;
	for (int i=l;i<=r;i++)
	if (midord[i]==preord[now])
	{
		mid=i;
		break;
	}
	if (mid!=l)
	{
		now++;
		T[noww].lson=make1(l,mid-1);
		T[T[noww].lson].father=noww;
	}
	else
	{
		T[noww].lson=-1;
	} 
	if (mid!=r)
	{
		now++;
		T[noww].rson=make1(mid+1,r);
		T[T[noww].rson].father=noww;
	}
	else
	{
		T[noww].rson=-1;
	} 
	return noww;
}
void make2()
{
	int sta[N][3];
	int l=1,r=n;
	int noww=1;
	int stn=1;
	int mid;
	sta[1][0]=0;sta[1][1]=1;sta[1][2]=n;
	while (stn>0)
	{
		int fa=sta[stn][0];
		l=sta[stn][1],r=sta[stn][2];
		T[noww].data=preord[noww];
		T[noww].father=fa;
		if (fa!=0)
		{
			if (T[fa].lson!=0)
			T[fa].rson=noww;
			else
			T[fa].lson=noww;
		}
		stn--;
		int a,b,c;
		for (int i=l;i<=r;i++)
		if (midord[i]==preord[noww])
		{
			mid=i;
			break;
		}
		if (mid!=l)
		{
			stn++;
			a=noww;
			b=l;
			c=mid-1;
		}
		else
		{
			T[noww].lson=-1;
		} 
		if (mid!=r)
		{
			if (mid==l) stn++;
			sta[stn][0]=noww;
			sta[stn][1]=mid+1;
			sta[stn][2]=r;
			if (mid!=l) stn++;
		}
		else
		{
			T[noww].rson=-1;
		}
		if (mid!=l)
		{
			sta[stn][0]=a;
			sta[stn][1]=b;
			sta[stn][2]=c;
		}
		noww++;
	}
	return;
}
void build()
{
	int l=1,r=n;
	now=1;
	cout<<"选择建树方式:1、递归 2、非递归"<<endl;
	int choose;
	cin>>choose;
	if (choose==1)
	{
		int head=make1(l,r);
	}
	else
	make2();
	return;
}
void init(int n,int ord[])
{
	for (int i=1;i<=n;i++) cin>>ord[i];
	return;
}
void start()
{
	cout<<"请输入树的节点的个数:";
	cin>>n;
	T=new Tree[N];
	for (int i=1;i<=n;i++)
	{
		T[i].data=T[i].father=T[i].lson=T[i].rson=0;
	}
	cout<<"请输入树的前序遍历:";
	preord=new int[N];
	init(n,preord);
	cout<<"请输入树的中序遍历:";
	midord=new int[N];
	init(n,midord);
	return;
}

猜你在找的数据结构相关文章