function.h代码如下
//
// Created by legion on 2024/3/5.
//
#ifndef INC_14_4_TREE_FUNCTION_H
#define INC_14_4_TREE_FUNCTION_H
#include <stdio.h>
#include <stdlib.h>
typedef char BiElemType;
typedef struct BiTNode{
BiElemType c;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;
//tag结构体是辅助队列使用的 队列是由链表实现的
typedef struct tag{
BiTree p;//树的某一个结点的地址值
struct tag *pnext;
}tag_t,*ptag_t;//这个链表结构体类型tag_t 为什么和结构体名不一致
#endif //INC_14_4_TREE_FUNCTION_H
下面是main.cpp代码:
#include "function.h"
int main() {
BiTree pnew;//用来指向新申请的树结点 结构体指针类型
BiTree tree=NULL;//tree是指向树根的,代表树
char c;
//定义队列 phead是队列头ptail是队列尾 listpnew指向新结点 pcur是指向当前父结点
ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur;
//输入abcdefghij
while(scanf("%c",&c))
{
if(c=='\n')
{
break;//读取换行结束
}
//calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0
pnew= (BiTree)calloc(1,sizeof(BiTNode));
pnew->c=c;//数据放进去
listpnew= (ptag_t)calloc(1,sizeof(tag_t));//给队列结点申请空间
listpnew->p=pnew;
if(NULL==tree)//如果树为空 放进去即为树根
{
tree=pnew;//树的根
phead=listpnew;//队列头
ptail=listpnew;//队列尾
pcur=listpnew;
continue;
} else{
ptail->pnext=listpnew;//新结点放入链表 通过尾插法
ptail=listpnew;//ptail指向队列尾部
}//pcur始终指向要插入的结点的位置
if(NULL==pcur->p->lchild)
{
pcur->p->lchild=pnew;//把新结点放到要插入结点的左边
} else if(NULL==pcur->p->rchild)
{
pcur->p->rchild=pnew;//把新结点放到要插入结点的右边
pcur=pcur->pnext;//左右都放了结点后,pcur指向队列下一个
}
}
return 0;
}
listpnew->p = pnew;
这行代码的含义是将指向新创建的树结点 pnew
的指针赋给 listpnew
结点中的指针 p
。这个 listpnew
结点实际上是一个辅助队列结点,而 pnew
则是树结点。
所以,listpnew->p
指向了最新创建的树结点 pnew
。当使用 pcur->p
时,实际上是在引用这个指针,表示当前要插入新结点的位置。
注意,这里的 p
不是树结点的值,而是指向树结点的指针。因此,在 if(NULL==pcur->p->lchild)
中,pcur->p
表示当前要插入新结点的位置的树结点,而 lchild
和 rchild
分别表示左子树和右子树。这里的 pcur->p->lchild
表示当前要插入新结点的位置的树结点的左子树是否为空,用于确定新结点应该插入的位置。
段代码中,listpnew->p
存储了指向新创建的树结点 pnew
的指针。由于 listpnew
是一个辅助队列结点,它的 p
指针确实是用来存储树结点的指针的。
因此,当我们需要引用树结点 pnew
的指针时,我们通过 listpnew->p
来获取。这样做的目的是为了在队列中维护一个顺序,确保新创建的树结点按照输入的顺序被插入到树中。
在这个特定的代码片段中,listpnew->p
的值即为最新创建的树结点的指针,而 pcur->p
在不同的时刻指向队列中当前要插入新结点的位置。这个位置可能是某个树结点的左子树或右子树。
代码中,辅助队列结构体中的指针 p
用于指向新创建的树结点,因此只能通过 listpnew->p
来获取新树结点的指针。(辅助队列为了获取新的树的指针 只能由自己的新队列结构体指针指向自己结构体中定义的树指针p来获取)
这种设计的目的是为了维护一个队列,确保树结点按照输入的顺序被插入。当你需要引用新创建的树结点时,通过 listpnew->p
就可以获取到最新的树结点指针。这种方式在构建树结构时保持了顺序,便于按照输入的先后顺序进行操作。
如果队列结构体中没有存储指向树结点的指针,那么就无法追踪最新的树结点,而这对于按顺序构建树结构是很重要的。
最终解释:
代码中,pcur
是用来迭代遍历队列的节点,而 pcur->p
是指向树节点的父节点。因此,通过 pcur->p->lchild
或 pcur->p->rchild
才能准确访问树节点的左孩子或右孩子。
-
pcur
是队列中的节点,通过pcur->p
可以访问到树节点,因为pcur->p
是指向树节点的指针。 -
在树节点的结构体中,包含了
lchild
和rchild
成员,用于表示左孩子和右孩子。 -
因此,为了访问树节点的左孩子,需要使用
pcur->p->lchild
,其中pcur->p
指向树节点,然后通过->lchild
访问左孩子。
这样的结构是为了正确表示二叉树的层次关系,确保在队列中迭代时能够访问到正确的父节点,从而插入新的节点。
代码中,pcur
是用来迭代遍历队列的节点,而 pcur->p
是指向树节点的父节点。因此,通过 pcur->p->lchild
或 pcur->p->rchild
才能准确访问树节点的左孩子或右孩子。
让我进一步说明一下:
-
pcur
是队列中的节点,通过pcur->p
可以访问到树节点,因为pcur->p
是指向树节点的指针。 -
在树节点的结构体中,包含了
lchild
和rchild
成员,用于表示左孩子和右孩子。 -
因此,为了访问树节点的左孩子,需要使用
pcur->p->lchild
,其中pcur->p
指向树节点,然后通过->lchild
访问左孩子。
这样的结构是为了正确表示二叉树的层次关系,确保在队列中迭代时能够访问到正确的父节点,从而插入新的节点。