数据结构代码题Day09
请设计一个算法,增加一个指向双亲节点的parent指针,并给指向指针赋值,并输出所有节点到根节点的路径。
- 题目分析
为什么要引出parent指针?
我们以往对二叉树的遍历过程顺序都是从根节点到叶子节点,通过层层的访问达到访问叶子节点,但是对于叶子结点到根节点的路径,无法通过现存的两个左指针和右指针进行访问,例如下图:
可以看到,再加入parent指针后,子节点有了对根节点的访问索引,能够从叶子结点访问到根节点,因此若需要求出叶子结点到根节点的路径,则必须要加入一个parent指针。
在加入一个指针工具后,对于二叉树的结构体代码更新如下:
//结构体
typedef struct BiTree{
char data;
struct BiTree *lchild,*rchild,*parent;
}*BiTree;
如何构建二叉树叶子结点到根节点的指针?
对于该问题就要首先想到在我们二叉树遍历的过程中的执行过程,例子图如下:
根据上述的例子图操作,我们对其叶子节点访问根节点的过程,加入两个结点p和q,其实现的代码如下:
p->parent = q;
q = p;
下面对代码进行解释,这里看上述的二叉树的结点不太好理解,下面改成线性路径图:
这里要引出之前学了单链表的时候学习的尾插法的逻辑实现,在一个单链表中若进行前进递归操作,便要通过next指针指向后继,并让后继重新赋值进行设计。
以上是对于单个结点进行添加parent指针,对于整个二叉树来讲,全部添加上parent的指向结点的代码实现是需要建立在先序遍历的基础模板上,选择前序遍历,是因为前序遍历先访问根节点,便于操作。
为二叉树指向指针parent赋值
实现代码:
//为其parent指针赋值
void GetFun(BiTree *p,BiTree *q){
if(p!=NULL){
p->parent = q;//单个结点指向前驱
q = p;//依次向前走
}
//左子树添加parent指针
GetFun(p->lchild,q);
//进行右子树添加parent
GetFun(p->rchild,q);
}
在为二叉树添加上parent的访问指针后,下面是实现叶子结点到跟节点的路径打印,由于二叉树的根节点不止一个,因此要实现多个路径打印,要先从一个节点到根节点路径实现为起步!
如何实现一个叶子结点到跟结点的路径打印
其实现操作图如下:
结合上述的例子图,其实现路径打印的步骤如下:
- 设置一个结点指针
- 若只有根节点一个结点,则直接输出data数据
- 设置一个while循环,条件为结点不为null
- 打印
- 采用不断递进的方式访问父节点。
其实现代码如下:
//打印单个结点到根节点路径
void printNode(BiTree *p){
while(p!=NULL){
//循环打印单个结点到根节点的数据
prinf("%s",p->data);
p = p->parent;//访问父亲节点
}
}
在对单个结点到跟结点的路径进行打印后,对于题目要求要求打印所有结点到根节点的路径。
打印所有结点到根节点的路径
- 采用先序遍历,对其进行单个数据结点进行打印;
- 若左子树不为NULL,打印左子树中结点到根节点的路径;
- 若右子树不为NULL,打印右子树中结点到根节点的路径。
实现代码:
//打印全部结点到根节点的路径
void Printf_allPath(BTree * p){
if(p = NULL){
return ;
}
if(p!= NULL){
printNode(p);//打印单个结点,调用上述函数
//左子树不为空
Printf_allPath(p->lchild);
//右子树不为NULL
Printf_allPath(p->rchild);
}
}
代码整合
在对上述题目进行分步骤进行实现后,对于解答代码进行整理得到如下的完整代码:
//结构体
typedef struct BiTree{
char data;
struct BiTree *lchild,*rchild,*parent;
}*BiTree;
//为其parent指针赋值
void GetFun(BiTree *p,BiTree *q){
if(p!=NULL){
p->parent = q;//单个结点指向前驱
q = p;//依次向前走
}
//左子树添加parent指针
GetFun(p->lchild,q);
//进行右子树添加parent
GetFun(p->rchild,q);
}
//打印单个结点到根节点路径
void printNode(BiTree *p){
while(p!=NULL){
//循环打印单个结点到根节点的数据
prinf("%s",p->data);
p = p->parent;//访问父亲节点
}
}
//打印全部结点到根节点的路径
void Printf_allPath(BTree * p){
if(p = NULL){
return ;
}
if(p!= NULL){
printNode(p);//打印单个结点,调用上述函数
//左子树不为空
Printf_allPath(p->lchild);
//右子树不为NULL
Printf_allPath(p->rchild);
}
}