二叉树相关操作(多使用递归)

目录

1,寻找公共祖先

2,二叉树的遍历

先序遍历 (NLR)

中序遍历(LNR)

后序遍历(LRN)

层次遍历​​​​​​​


1,寻找公共祖先

 已知一棵二叉树按顺序存储结构进行存储,求编号分别为i和j的两个结点的最近的公共祖先的结点的值。

算法:采用递归的方法。
操作过程:
    1、最差的结果是最近的公共祖先的结点是根结点,此时i和j分别在左右树。
   2、 一直往上找,找i的祖先和j的祖先。并分别将祖先赋名给i和j。
    当i = j时,i和j是一个结点,则说明找到了公共祖先。

Elemtype Comm_Ancestor(SqTree T, int i, int j)
{
	if (T[i] != '#' && T[j] != '#')
	{
		//假设#是该结点不存在。
		while (i != j)
		{
			if (i > j)
			{
				//i>j时可能i是j的下一层结点(有可能是孩子,也可能不是)
				//可能是右(堂)兄弟
				i = i / 2;
			}
			else
			{
				j = j / 2;
			}
			return T[i];
		}	
	}	
}

2,二叉树的遍历

时间复杂度都是O(n)

先序遍历 (NLR)

特点:根左右

操作过程:

1:若二叉树为空,则什么也不做;

2:访问根结点,接下来先序遍历左子树,先序遍历右子树。

        对于左子树和右子树同样进行先序遍历。

算法:递归

void PreOrder(BiTree T)
{
	if (T != NULL)
	{
		visit(T);				//访问根结点
		PreOrder (T -> lchild);//访问左子树
		PreOrder (T -> rchild);//访问右子树
	}
}

特点:根左右

操作过程:

1:若二叉树为空,则什么也不做;

2:访问根结点,接下来先序遍历左子树,先序遍历右子树。

        对于左子树和右子树同样进行先序遍历。

算法:借助栈

void PreOrder2(BiTree T)
{
	//初始化栈S,p是遍历指针。
	InitStack(S);
	BiTree p = T;
	
	//栈不空或P不空时循环
	while (p || !IsEmpty(S))
	{
		if (p)
		{
			//一路向左
			visit(p);
			Push(S,p);//访问当前结点,并入栈
			p = p -> lchild;//左孩子不空,一直向左走
		}
		else
		{
			//出栈,并转向出栈结点的右子树
			Pop(S,p);//栈顶元素出栈
			p = p -> rchild;//向右子树走,p赋值为当前结点的右孩子
		}
		//返回while循环继续继续进入if-else语句。	
	}
}

中序遍历(LNR)

特点:左根右

操作过程:

1:若二叉树为空,则什么也不做;

2:中序遍历左子树,访问根结点,中序遍历右子树。

算法:递归

void InOrder(BiTree T)
{
	if (T != NULL)
	{
		InOrder(T -> lchild); //遍历递归左子树
		visit(T);			  //访问根结点
		InOrder (T -> rchild);//遍历递归右子树
	}
}

特点:左根右

操作过程:

1:若二叉树为空,则什么也不做;

2:中序遍历左子树,访问根结点,中序遍历右子树。

算法:借助栈

void InOrder2(BiTree T)
{
	//初始化栈S,p是遍历指针。
	InitStack(S);
	BiTree p = T;
	
	//栈不空或P不空时循环
	while (p || !IsEmpty(S))
	{
		if (p)
		{
			//一路向左
			Push(S,p);//当前结点入栈
			p = p -> lchild;//左孩子不空,一直向左走。
		}
		else
		{
			//出栈,并转向出栈结点的右子树
			Pop(S,p);
			visit(p);//栈顶元素出栈,访问出栈结点
			p = p -> rchild;//向右子树走,p赋值为当前结点的右孩子
		}
		//返回while循环继续继续进入if-else语句。	
	}
}

后序遍历(LRN)

特点:左右根

操作过程:

1:若二叉树为空,则什么也不做;

2:后序遍历左子树,后序遍历右子树,访问根结点。

算法:递归

void PostOrder(BiTree T)
{
	if (T != NULL)
	{
		PostOrder(T -> lchild); //遍历递归左子树
		PostOrder (T -> rchild);//遍历递归右子树
		visit(T);			    //访问根结点
	}
}

层次遍历

借助队列

void levelOrder(BiTree T)
{
	InitQuene(Q);//初始化辅助队列
	BiTree p;
	EnQuene(Q,T);//将根结点入队
	while (!IsEmpty(Q))
	{
		//队列不空循环
		DeQuene(O,p);//队头结点出队
		visit(p);//访问出队结点
		if (p -> lchild != NULL)
		{
			EnQuene(Q,p -> lchild);//左子树不空,则左子树根结点入队
		}
		if (p -> rchild != NULL)
		{
			EnQuene(Q,p -> rchild);//右子树不空,则右子树根结点入队
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wmpreturn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值