数据结构代码题Day09--<视频Day49>

数据结构代码题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);
		}
	}

在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值