线索二叉树
Published on 2024-04-02 08:47 in 分类: 数据结构 with 真真夜夜
分类: 数据结构

线索二叉树

二叉树线索化

⚠️ 被线索化之后的lchildrchild表示前驱与后继

// 中序遍历对二叉树线索化的递归算法
void InThread(ThreadTree &p, ThreadTree &pre) {
	if (p != NULL) {
    	InThread(p->lchild, pre);	// 一直递归到最左子树  
        
        /* 中序遍历 */
        if(p->lchild == NULL) {		// 没有左孩子就指向前驱
        	p->lchild = pre;		// 建立当前节点的前驱线索
            p->ltag = 1;
        }
        if(pre!=NULL&&pre->rchild==NULL){
        	pre->rchild = p;	// 建立前驱节点的后继线索
            pre->rtag = 1;
        }
        pre = p;
        /* 中序遍历 */
        
        InThread(p->rchild, pre);	// 递归线索化右子树
    }
}

// 中序遍历建立中序线索二叉树
void CreateInThread(ThreadTree T) {
	ThreadTree pre = NULL;
    if (T != NULL) {
    	pre->rchild = NULL;
    	pre->rtag = 1;
    }
}

算法的思想很简单:算法整体思路与中序遍历一致,按照“左根右”的顺序编排代码。

  • 首先InThread一直递归到最左子树;
  • 其次我们要帮助p节点寻找前驱节点,建立前驱线索;
  • 之后我们要帮助pre节点寻找后继节点,建立后继线索;
  • 最后InThread向右递归;

总结:找到某个状态,完整状态的转变,最后递归解决问题。

附上先序代码与后序代码

// 先序线索化
void PreThread(ThreadTree &p, ThreadTree &pre) {
	if (p != NULL) {
    	if (p->lchild) {	// 左子树为空,建立前驱线索
        	p->lchild = pre;
            p->ltag = 1;
        }
    
    	if (pre!=NULL && pre->rchild==NULL) {   // 建立前驱节点的后继线索
    		pre->rchild = p;
        	pre->rtag = 1;
    	}
      pre = p;
      if (p->ltag == 0)	// 关键点,防止爱滴魔力转圈圈
          PreThread(p->lchild, pre);
      PreThread(p->rchild, pre);
	}
}

void CreatePreThread(ThreadTree T) {
	ThreadTree pre = NULL;
    if (T != NULL) {
    	PreThread(T, pre);
        if(pre->rchild == NULL) 
        	pre->rtag = 1;
    }
}
// 后序线索化
void PostThread(ThreadTree p, ThreadTree &pre) {
	if(p!=NULL) {   // 递归结束条件
    	PostThread(p->lchild, pre);
        PostThread(p->rchild, pre);
    	if(p->lchild=NULL) {    // 左子树为空,建立前驱线索
        	p->lchild = pre;
            p->ltag = 1;
        }
        if(pre!=NULL&&pre->rchild==NULL){   // 建立前驱节点的后继线索
        	pre->rchild = p;
            pre->rtag = 1;
        }
        pre = p;
    }
}

// 后序线索化二叉树
void CreatePostThread(ThreadTree T) {
	ThreadTree pre = NULL;
    if(T!=NULL) {
    	PostThread(T, pre);
        if(pre->rchild==NULL) {
        	pre->rtag = 1;
        }
    }
}

线索化二叉树寻找前驱/后继

对于中序线索二叉树中寻找指定节点*p的中序后继next

  • p->rtag == 1, next = p->rchild
  • p->rtag == 0, p右子树中最左下节点
ThreadNode *Firstnode(ThreadNode *p) {
    // 有左子树就一直往左走
    while(p->ltag == 0) {   
        p = p->lchild;  
    }
    return p;
}

ThreadNode *NextNode(ThreadNode *p) {
    // 如果rtag==0,就从右子树中找到最左下的节点
    if(p->rtag == 0)    return Firstnode(p->rchild);
    else return p->rchild;  // rtag==1 则直接返回后继
}

// 中序线索化二叉树进行中序遍历(非递归)
void Inorder(ThreadNode *T) {
    for(ThreadNode *p = Firstnode(T); p!=NULL; p=Nextnode(p)) {
        visit(p);
    }
}

对于中序线索二叉树中寻找指定节点*p的中序前驱pre

  • p->ltag == 1, pre = p->lchild
  • p->rltag == 0, p左子树中最右下节点
ThreadNode *Lastnode(ThreadNode *p) {
    while(p->rtag==0) { // 有右子树就一直往右走
        p = p->rchild;
    }
    return p;
}

ThreadNode *Prenode(ThreadNode *p) {
    // 寻找左子树最右下节点
    if(p->ltag==0)  return Lastnode(p->lchild);
    else return p->lchild;
}

// 对中序线索二叉树进行逆向中序遍历
void RevInorder(ThreadNode *T) {
    for(ThreadNode *p=Lastnode(T); p!=NULL; p=Prenode(p))
        visit(p);
}

对于先序线索二叉树中寻找指定节点*p的先序后继next

  • p->rtag == 1, pre = p->lchild
  • p->rtag == 0, p是左孩子或右孩子的根节点

对于先序线索二叉树中寻找指定节点*p的先序前驱pre

  • p->ltag == 1, pre = p->lchild
  • p->ltag == 0, 土办法或者改用三叉链表
      1. 如果能找到p的父节点且p是左孩子,p的父节点即为pre
      2. 如果能找到p的父节点且p是右孩子,p的兄弟节点为空,p的父节点即为pre
      3. 如果能找到p的父节点且p是右孩子,p的左兄弟节点不为空,p的左兄弟节点的最右下节点即为pre
      4. p为根节点,无前驱
        img

对于后序线索二叉树寻找指定节点*p的后序后继next

  • p->ltag == 1, pre = p->lchild
  • p->ltag == 0, 土办法或者改用三叉链表
      1. 如果能找到p的父节点且p是右孩子,p的父节点即为next
      2. 如果能找到p的父节点且p是左孩子,p的兄弟节点为空,p的父节点即为next
      3. 如果能找到p的父节点且p是左孩子,p的右兄弟节点不为空,p的右兄弟节点的最左下节点即为next
      4. p为根节点,无后继
        img

相关考点:

  1. 后序线索树的遍历仍然需要栈的支持
    分析:普通的二叉树不管是递归算法(隐含递归栈),还是非递归算法都需要栈的支持。先序和中序线索二叉树由于线索化,不需要栈(因为能找到下一个遍历对象)。
posted @   真真夜夜  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示