二叉树欧拉环游遍历及其应用
学过数据结构的童鞋应该都对二叉树的遍历有所了解,如先序、中序、后序和层次遍历。二叉树还有一种遍历方式为欧拉环游遍历
欧拉环游遍历:
欧拉环游遍历就是绕着二叉树的“外围”走一圈。如下图所示:
其中,每个结点被访问了三次“左边访问”(浅蓝色标记)、“下方访问”(绿色标记)、“右边访问”(粉色标记),且叶子结点的三次访问发生在同一时间。
让我们来想想欧拉环游遍历和其他几种遍历的关系,当每个结点仅仅在左边被访问时,其遍历是等价于先序遍历的,同样的,当仅仅只在下边和右边被访问时,遍历结果等价于中序遍历和后序遍历。
欧拉环游遍历代码:
//欧拉环游遍历
void EulerTour_Traverse(BTree T)
{
printf("Now left: %c \n",T->val);//访问左
if(T->lchild)
EulerTour_Traverse(T->lchild);
printf("Now below: %c \n",T->val);//访问下
if(T->rchild)
EulerTour_Traverse(T->rchild);
printf("Now right: %c \n",T->val);//访问右
}
上图二叉树遍历结果:(先序创建二叉树)
那么欧拉环游遍历可以解决什么问题呢?
后代数量统计
通过欧拉环游遍历可以方便的得到某个结点的后代数量。初始时设置一个计数器,初始值为0。然后在每次访问结点的左方时递增计数器,当访问到目标结点左方时,记录下此时的计数器值c,当访问到目标结点的右方时,计算当前计数器值c’和c的差值,结果即为该结点的后代数量。
代码如下:
//获得结点值为tar的结点的后代数量
void GetOffspring(BTree T,NodeType tar)
{
count++;//全局变量,初始为0
if(T->val == tar)
count_start = count;//访问到目标结点时进行记录
if(T->lchild)
GetOffspring(T->lchild,tar);
if(T->rchild)
GetOffspring(T->rchild,tar);
if(T->val == tar)
{
offsprings = (count - count_start);//差值即为后代个数
}
}
结果如下:(求结点C的后代个数)
打印完整待括号表达式
利用欧拉环游遍历可以打印完整的带括号的表达式。
void PrintExpression(BTree T)
{
printf("(");
if(T->lchild)
PrintExpression(T->lchild);
printf("%c",T->val);
if(T->rchild)
PrintExpression(T->rchild);
printf(")");
}
对于下图的二叉树,其完整待括号表达式为(((3)-(1))*((2)/(5)))
。