二叉树(二)

五、线索二叉树

    当以二叉链表作为存储结构时,只能找到结点的左、右孩子信息,而不能直接得到结点在任一序列中的前驱和后继信息,

    这种信息只有在遍历的动态过程中才能得到。

    

                                                                   线索二叉树结点结构

       规定:

                若结点有左子树,则其LChild域指向其左孩子,否则LChild域指向其前驱结点;

                若结点有右子树,则其RChild域指向其右孩子,否则RChild域指向其后继结点。

       其中:

                LTag:

                        0----LChild域指向结点的左孩子

                        1----LChild域指向结点的遍历前驱

                RTag:

                        0----RChild域指向结点的右孩子

                        1----RChild域指向结点的遍历后继

        在这种存储结构中,指向前驱和后继的结点的指针称为线索。以这种结构组成的二叉链表作为二叉树的的存储结构,

        称为线索链表。对二叉树以某种次序进行遍历并且加上线索的过程称为线索化。线索化了的二叉树称为线索二叉树。

        实质:

                将二叉链表中的空指针域上填上相应结点的遍历前驱或遍历后继结点的地址,而前驱和后继的地址只能在动态的

                遍历过程中才能得到,因此线索化的过程即为在遍历过程中修改空指针域的过程。

        建立中序线索树:

                 (1)算法思想:

                            设置一个指针pre,始终记录刚访问过的结点。

                                    如果当前遍历结点root的左子域为空,则让左子域指向pre;

                                   如果前驱pre的右子域为空,则让右子域指向当前遍历结点root;

                                   为下次做准备,当前访问结点root作为下一个访问结点的前驱pre。 

                 (2)算法描述:                

                            void  Inthread(BiTree  root)

                            {

                                    if(root != NULL)

                                    {

                                            Inthread(root->LChild);    //线索化左子树

                                            if(root->LChild == NULL)

                                            {

                                                    root->LTag = 1;

                                                    root->LChild = pre;

                                            }

                                           if(pre != NULL && root->RChild == NULL)

                                          {

                                                   pre->RChild = root;

                                                   pre->RTag = 1;

                                          }

                                          pre = root;      //当前访问结点为下一个访问结点的前驱

                                         Inthread(root->RChild);        //线索化右子树

                                    }

                            }

           在线索二叉树中找前驱结点

                        (1)算法思想

                             对于结点p,当p->LTag = 1时,p->LChild指向p的前驱;当p->LTag = 1时,p->LChild指向p的左孩子。

                             作为根p的前驱结点,它是中序遍历p的左子树时访问的最后一个结点,即左子树的“最右下端”结点。

                        (2)算法描述

                              BiTNode*  InPre(BiTNode* p)

                             {

                                        if(p->LTag == 1)

                                        {

                                                pre = p->LChild;

                                        }

                                       else

                                        {

                                                for(q = p->LChild;q->RTag == 0;q = q->RChild)

                                                {

                                                        pre = q;

                                                }

                                        }

                                      return pre;

                             }

           在线索二叉树中找后继结点

                        (1)算法思想

                                   对于结点p,若p->RTag = 1时,p->RChild即为p的后继结点;当p->RTag = 0时,说明p有右子树,

                                   此时p的中序遍历后继结点为其右子树的“最左下端”的结点。

                        (2)算法描述

                                   BiTNode*   InNext(BiTNode  *p)

                                  {

                                            if(p->RTag == 1)

                                            {

                                                    next = p->RChild;

                                            }

                                           else

                                           {

                                                    for(q = p->RChild;q->LTag == 0;q = q->LChild)

                                                    {

                                                            next = q;

                                                    }

                                            }

                                           return next;

                                 }

           遍历中序线索树

                       (1)算法思想

                                求出某种遍历次序下第一个被访问结点;

                                然后连续求出刚访问结点的后继结点,直至所有的结点均被访问。

                       (2)算法描述

                                BiTNode*  InFirst(BiTree bt)

                                {

                                       BiTNode *p = bt;

                                       if(p =- NULL)

                                       {

                                                return NULL;

                                        }

                                       while(p->LTag == 0)

                                        {

                                                p = p->LChild;

                                        }

                                        return p;

                                }                

                

                                void TInOrder(BiTree bt)

                                {

                                        BiTNode * p;

                                        p = InFirst(bt);

                                        while(p != NULL)

                                        {

                                                visit(p);

                                                p = InNext(p);

                                        }

                                }

### 关于二叉树级指针的概念 在C/C++编程中,二叉树是一种常见的数据结构,用于表示层次化的节点关系。每个节点最多有两个子节点:左子节点和右子节点。而级指针是指指向指针的指针,在操作动态分配内存或者修改函数参数中的指针本身时特别有用。 #### 二叉树定义与基本操作 对于二叉树而言,通常通过结构体来定义其节点: ```c++ struct TreeNode { int val; struct TreeNode *left; // 左孩子 struct TreeNode *right; // 右孩子 }; ``` 当涉及到插入新节点、删除现有节点以及遍历整棵树的操作时,可能会遇到需要改变某个节点地址的情况,这时就需要用到级指针[^1]。 #### 使用级指针实现的方法 考虑一个简单的例子——向已有的叉查找树(Binary Search Tree, BST) 中插入一个新的数值。为了能够更新根节点的位置(即可能要创建新的根),可以传递指向根节点指针的指针给插入函数: ```cpp void insertIntoBST(TreeNode **rootRef, int newValue){ if (*rootRef == nullptr){ *rootRef = new TreeNode{newValue,nullptr,nullptr}; }else{ TreeNode* current=*rootRef; while(true){ if(newValue<current->val){ if(current->left==nullptr){ current->left=new TreeNode{newValue,nullptr,nullptr}; break; } current=current->left; } else { /* 类似处理右侧 */ ... } } } } ``` 这段代码展示了如何利用级指针`TreeNode** rootRef` 来允许被调用者更改传入的 `root` 参数所指向的对象。这使得即使是在递归或迭代过程中也可以安全有效地调整树形结构[^2]。 #### 应用场景分析 使用级指针的主要优势在于能够在不返回额外值的情况下直接修改外部作用域内的指针变量。这对于构建自平衡叉搜索树(如AVL Trees 或 Red-black trees),或是执行涉及大量结构调整的数据结构算法来说非常重要。此外,在某些情况下还可以简化接口设计并提高性能效率[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值