读书

你还不知道线索二叉树吗?看这篇就对了,一通百通

2022-06-02  本文已影响0人  管彤Java架构师

线索二叉树的概念

概念:

线索二叉树的实现

前驱和后继的信息只有在遍历二叉树时才能得到。而在遍历二叉树时便可以线索化。

线索化:

线索二叉树的遍历:

线索二叉树节点:

/* 线索二叉树节点结构 */
typedef int tree_elem_type;
/* link_e==0表示指向左右孩子指针, */
/* thread_e==1表示指向前驱或后继的线索 */
typedef enum 
{
link_e, thread_e
} 
pointer_tag_e;
typedef struct tree_node
{    
struct tree_node *lchild; 
// 左子域    
struct tree_node *rchild; 
// 右兄域    
pointer_tag_e ltag; 
// 左标志    
pointer_tag_e rtag; 
// 右标志    
tree_elem_type data; 
// 数据
}
binary_tree_node_t;

线索化代码参考下面参考代码。

线索二叉树的寻点思路二

以中序线索二叉树为例,令 P 所指节点的某个结点。查找 p 所指结点的后继点的方法:

  1. 若 p->rtag==1,则 p->rchild 指向其后继节。
  2. 若 p->rtag==0,则 p 所指结点的中序后继必然是其右子树中进行中序遍历时得到的第一个结点。也就是 p 的右子树中“最左下”的结点。这点可以利用递归。也可以参考下面代码的非递归方法。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

寻点代码参考下面代码。

类双向链表参考图

image.png

参考代码

中序遍历线索化

binary_tree_node_t *pre = NULL;
 /* 全局变量, 上一访问节点 */
/* 中序遍历进行中序线索化 */
void in_threading(binary_tree_node_t *p){     
if(p)    
{        
in_threading(p->lchild); 
/* 递归左子树线索化 */        
if(!p->lchild) 
/* 没有左孩子 */        
{            
p->ltag = thread_e;
 /* 前驱线索 */            
p->lchild = pre;
 /* 左孩子指针指向前驱 */        
}        
if(!pre->rchild)
 /* 前驱没有右孩子 */        
{            
pre->rtag = thread_e; 
/* 后继线索 */            
pre->rchild = p; 
/* 前驱右孩子指针指向后继(当前结点p) */        
}        
pre = p; 
/* 保持pre指向p的前驱 */        
in_threading(p->rchild);
 /* 递归右子树线索化 */    
}
}
/* 中序遍历二叉树tree,并将其中序线索化,tree_list指向头结点 */int in_order_threading(binary_tree_node_t **tree_list_p, binary_tree_node_t *tree)
{     
*tree_list_p = (binary_tree_node_t *)
malloc(sizeof(binary_tree_node_t));    
if(!*tree_list_p)        
return -1;    
(*tree_list_p)->ltag = link_e; 
/* 孩子,用于指根 */    
(*tree_list_p)->rtag = thread_e; 
/* 线索,只最右下。即是链尾 */    
(*tree_list_p)->rchild = (*tree_list_p); 
/* 初始化:右指针回指 */    
if(!tree) 
/* 若二叉树空,则左指针回指 */        
(*tree_list_p)->lchild = *tree_list_p;    
else    
{        
(*tree_list_p)->lchild = tree;        
pre = (*tree_list_p);        
in_threading(tree); 
/* 中序遍历进行中序线索化 */        
pre->rchild = *tree_list_p;        
pre->rtag = thread_e; 
/* 最后一个结点线索化 */        
(*tree_list_p)->rchild = pre;    
}    
return 0;
}
/* 中序遍历二叉线索树tree(头结点)的非递归算法 */
int in_order_traverse_tree_list(binary_tree_node_t *tree)
{     
binary_tree_node_t *p = NULL;    
p = tree->lchild; 
/* p指向根结点 */    
while(p != tree)    
{         
/* 找到最左下节点 */        
while(p->ltag == link_e)            
p = p->lchild;        
if(!visit(p->data)) 
/* 访问其左子树为空的结点 */            
return -1;         
 /* 判断是否有后继,且不是整个树的最右下节点 */        
while(p->rtag == thread_e && p->rchild != tree)        
{            
p = p->rchild;            
visit(p->data); 
/* 访问后继结点 */        
}        
p = p->rchild; 
/* 切换到右子树。然后继续中序遍历该右子树 */    }    
return -1;
}
上一篇 下一篇

猜你喜欢

热点阅读