二叉树的存储结构--链式存储
二叉树的遍历-前序遍历
两个 return,两种退出函数的方式
手写
return;仅当T==NULL(空节点)触发,直接结束当前这一次函数调用。隐式自动 return(重点!你疑惑的点)
当节点不为 NULL,函数中所有代码全部执行完毕,走到函数最后的大括号
},C 语言 void 函数会自动返回上一层调用处,不需要写 return 关键字。
❗每一次函数调用,都有自己独立的局部变量 T。下层函数的 T,不会修改上层函数的 T。
示例:执行 preOrder (H) 的完整流程
- T=H,H 不为 NULL,跳过 if,打印 H。
- 执行
preOrder(H->lchild):左孩子为空,触发手写return;,回到 H 函数,左递归语句结束。 - 执行
preOrder(H->rchild)(节点 K)- T=K,不为 NULL,打印 K
- K 左为空:手写 return,回到 K 函数
- K 右为空:手写 return,回到 K 函数
- K 内部全部代码跑完,遇到
},隐式自动 return,回到 H 函数。
- H 函数:printf、左递归、右递归全部执行完成。走到
},隐式自动 return,回到 D 函数中调用 H 的那一行。
#include <stdio.h> typedef char ElemType; tyedef struct TreeNoed { ElemType data; struct TreeNode *lchild; struct TreeNode *rchild; }TreeNode; typedef TreeNode* BigTree;//指针的指针 char str[]="ABDH#K###E##CFI###G#J##"; //传入节点从左到右 int idex=0; void createTree(BigTree *T)//BeTree是一级指针,BeTree*是二级指针,也就是传的参数是二级指针 { //通过递归的方式造树 ElemType ch; ch=str[idx++]; if(ch=='#') { *T=NULL; } else { *T=(BiTree)malloc(sizeof(TreeNode)); //赋值 创建节点 (*T)->data=ch; createTree(&(*T)->lchild); createTree(&(*T)->rchild); } } void inOrder(BiTree T) { if(T==NULL) { return; } printf("%c ",T->data); preOrder(T->lchild); preOder(T->rchild); } int main() { BiTree T; createTree(&T); preOrder(T); printf("\n"); return 0; }中序遍历
#include <stdio.h> typedef char ElemType; tyedef struct TreeNoed { ElemType data; struct TreeNode *lchild; struct TreeNode *rchild; }TreeNode; typedef TreeNode* BigTree;//指针的指针 char str[]="ABDH#K###E##CFI###G#J##"; //传入节点从左到右 int idex=0; void createTree(BigTree *T)//BeTree是一级指针,BeTree*是二级指针,也就是传的参数是二级指针 { //通过递归的方式造树 ElemType ch; ch=str[idx++]; if(ch=='#') { *T=NULL; } else { *T=(BiTree)malloc(sizeof(TreeNode)); //赋值 创建节点 (*T)->data=ch; createTree(&(*T)->lchild); createTree(&(*T)->rchild); } } void inOrder(BiTree T) { if(T==NULL) { return; } preOrder(T->lchild); printf("%c ",T->data); preOder(T->rchild); } int main() { BiTree T; createTree(&T); preOrder(T); printf("\n"); return 0; }后序遍历
#include <stdio.h> typedef char ElemType; tyedef struct TreeNoed { ElemType data; struct TreeNode *lchild; struct TreeNode *rchild; }TreeNode; typedef TreeNode* BigTree;//指针的指针 char str[]="ABDH#K###E##CFI###G#J##"; //传入节点从左到右 int idex=0; void createTree(BigTree *T)//BeTree是一级指针,BeTree*是二级指针,也就是传的参数是二级指针 { //通过递归的方式造树 ElemType ch; ch=str[idx++]; if(ch=='#') { *T=NULL; } else { *T=(BiTree)malloc(sizeof(TreeNode)); //赋值 创建节点 (*T)->data=ch; createTree(&(*T)->lchild); createTree(&(*T)->rchild); } } void inOrder(BiTree T) { if(T==NULL) { return; } preOrder(T->lchild); preOder(T->rchild); printf("%c ",T->data); } int main() { BiTree T; createTree(&T); preOrder(T); printf("\n"); return 0; }非递归前序遍历
二叉树性质
线索二叉树
存储结构
#include <stdio.h> #include <stdlib.h> typedef cahr ElemType; //定义线索二叉树的节点结构 typedef struct ThreadNode{ ElemType data; struct ThreadNode *lchild; struct ThreadNode *rchild; int ltag; //左标志:0表示左孩子,1表示前驱线索 int rtag; // 右标志:0表示有右孩子,1表示后驱线索 }ThreadNode; typedef ThreadNode* ThreadTree; char str[]="ABDH##I##EJ###CF##G##"; int idx=0; ThreadTree prev; //创建普通二叉树 void createTree(ThreadTree *T){ ElemType ch=str[idx++]; if(ch=='#'){ *T=NULL;//空节点 }else{ *T=(TreadTree)malloc(sizeof(ThreadNode)); (*T)->data=ch; createTree(&(*T)->lchild); //构建左子树,0为有左子树,1为有线索 (*T)->ltag=(*T)->lchild ? 0:1; createTree(&*(T)->rchild); (*T)->rtag=(*T)>rchild ? 0:1; } //中序线索化函数:建立前驱/后驱关系 void threading(ThreadTree T){ if(T!=NULL){ threading(T-lchild); //递归线索化左子树 // 如果当前节点左指针为空,建立前驱线索 if(T->ltag==1) T->lchild=prev; //如果前一个节点的右指针为空,建立其后继线索指向当前节点 if(prev&&prev->tag==1) prev->rchild=T; prev=T; //更新 prev为当前节点 threading(T->child); //线索化递归右子树 } } //创建头节点,调用线索化过程,建立线索二叉树 void inOderThreading (Threading *T,ThreadTree *head) { *head=(ThreadTree)malloc(sizeof(ThreadNode)); (*head)->ltag=0; (*head)->rtag=1; (*head)->rchild=*head; //初始时回指向自己 if(*T==NULL){ (*head)->lchild=*head; //空树的情况 }else{ (*head)->lchild=*T; //头节点左指向根节点 prev=*head; //初始化前驱指针 保存着上一个访问的节点 threading(*T); //中序线索化整个树 //补全最后一个节点的后继线索 prev->rchild=*head; //prev->rtag=1; (*head)->rchild=prev; } } //中序线索遍历线索化后的二叉树(非递归) void inOder(ThreadTree T){ ThreadTree curr=T->lchild; //从头节点的左子树开始 while(curr!=T){ //沿左孩子一直走到底 while(curr->ltag==0) curr=curr->lchild; //直至找不到 输出 printf("%c",curr->data); //顺着线索一直向右访问所有后继 while(curr->rtag==1&&curr->rchild!=T){ curr=curr->rchild; printf("%c",curr->data); } //进入当前节点的右子树 curr=curr->rchild; } } int main(){ ThreadTree T,head; //head 为头节点 createTree(&T); //创建原始二叉树 inOderhreaing(&T,&head); //执行线索化处理 printf("中序遍历结果:"); inOder(head); retrn 0; //遍历线索二叉树 }