说明:
一、二叉树为什么要线索化:
二叉树线索化之后,可以使二叉树像链表一样对其中的元素进行访问,而不需要再利用递归来遍历二叉树,提高了代码的运行效率。
二、 二叉树线索化视图:
代码实现:
一、创建一个结构体:
typedef struct Node{
int key,ltag,rtag; //key表示二叉树的值,ltag,rtag分别表示左线索,右线索
struct Node *lchild,*rchild; //lchild,rchild分别表示左子树,右子树
}Node; //Node可以理解为一个树节点
二、实现一个函数(能够初始化树节点数据):
Node *getNewNode(int key){
Node *p=(Node *)malloc(sizeof(Node)); //给指针开辟一个内存空间
p->key=key; //为二叉树的节点赋值
p->ltag=p->rtag=0; //左、右线索初始化为0,表示每条线索头尾都有真实节点连接
p->lchild=NULL; //初始化左子树
p->rchild=NULL; //初始化右子树
return p;
}
三、实现一个函数(能够生成二叉树结构):
Node *insert(Node *head,int key){
if(head==NULL)return getNewNode(key); //如果头节点为空,就返回一个新的节点
if(rand()%2) head->lchild=insert(head->lchild,key); //随机生成二叉树的左子树(递归)
else head->rchild=insert(head->rchild,key); //随机生成二叉树的右子树(递归)
return head;
}
四、实现一个函数(能够释放指针所占用的内存空间):
void clear(Node *root){
if(root==NULL)return; //判断头节点是否为空
if(root->ltag==0)clear(root->lchild); //ltag为0,表示有真实左子树节点存在(递归)
free(root); //释放空间
if(root->rtag==0)clear(root->rchild); //ltag为0,表示有真实右子树节点存在(递归)
return;
}
五、实现一个函数(能够将二叉树的每个节点线索化):
Node *pre_Node=NULL,*lineNode=NULL; //pre_Node表示前一个节点,lineNode表示二叉树的中间节点
void line(Node *root){ //中序线索化
if(root==NULL)return; //判断头节点是否为空
if(root->ltag==0)line(root->lchild); //如果ltag为0,则表示真实的左子树节点存在,可以递归操作
if(lineNode==NULL) lineNode=root; //如果lineNode为空,则需要将root赋值给lineNode(二叉树的起始节点)
if(root->lchild==NULL){ //如果左子树为空
root->lchild=pre_Node; //左子树指向其前驱
root->ltag=1; //表示不存在的节点需要线索化,ltag赋值为1
}
if(pre_Node&&pre_Node->rchild==NULL){ //如果pre_Node存在且其右子树为空
pre_Node->rchild=root; //右子树指向其后继
pre_Node->rtag=1; //表示不存在的节点需要线索化,ltag赋值为1
}
pre_Node=root; //下一个节点看上一个节点
if(root->rtag==0)line(root->rchild); 如果rtag为0,则表示真实的右子树节点存在,可以递归操作
return;
}
void line1(Node *root){ //封装
line(root); //中序线索化
pre_Node->rchild=NULL; //最右边的尾节点无节点可以连接,强制为空
pre_Node->rtag=1; //表示尾节点需要线索化,ltag赋值为1
return;
}
六、实现一个函数(能够遍历线索化后的二叉树):
Node *output(Node *p){
if(p->rtag==1) return p->rchild; //如果为rtag为1,则返回其右子树节点
p=p->rchild; //获取下一个右节点
while(p->ltag==0&&p->lchild){ //如果左子树节点存在
p=p->lchild; //循环获取左子树节点
}
return p;
}
完整代码:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
typedef struct Node{
int key,ltag,rtag;
struct Node *lchild,*rchild;
}Node;
Node *getNewNode(int key){
Node *p=(Node *)malloc(sizeof(Node));
p->key=key;
p->ltag=p->rtag=0;
p->lchild=NULL;
p->rchild=NULL;
return p;
}
Node *insert(Node *head,int key){
if(head==NULL)return getNewNode(key);
if(rand()%2) head->lchild=insert(head->lchild,key);
else head->rchild=insert(head->rchild,key);
return head;
}
void clear(Node *root){
if(root==NULL)return;
if(root->ltag==0)clear(root->lchild);
free(root);
if(root->rtag==0)clear(root->rchild);
return;
}
Node *pre_Node=NULL,*lineNode=NULL;
void line(Node *root){
if(root==NULL)return;
if(root->ltag==0)line(root->lchild);
if(lineNode==NULL) lineNode=root;
if(root->lchild==NULL){
root->lchild=pre_Node;
root->ltag=1;
}
if(pre_Node&&pre_Node->rchild==NULL){
pre_Node->rchild=root;
pre_Node->rtag=1;
}
pre_Node=root;
if(root->rtag==0)line(root->rchild);
return;
}
void line1(Node *root){
line(root);
pre_Node->rchild=NULL;
pre_Node->rtag=1;
return;
}
Node *output(Node *p){
if(p->rtag==1) return p->rchild;
p=p->rchild;
while(p->ltag==0&&p->lchild){
p=p->lchild;
}
return p;
}
void output1(Node *p){
if(p->lchild)output1(p->lchild);
printf("%d ",p->key);
if(p->rchild)output1(p->rchild);
return;
}
int main(){
srand(time(0));
Node *p=NULL;
for(int i=0;i<10;i++){
p=insert(p,rand()%100+1);
}
output1(p);
printf("\n");
pre_Node=lineNode=NULL;
line1(p);
p=lineNode;
while(p){
printf("%d ",p->key);
p=output(p);
}
clear(p);
return 0;
}
文章到此结束!