线索二叉树

一、线索二叉树的原理

    通过考察各种二叉链表,不管儿叉树的形态如何,空链域的个数总是多过非空链域的个数。

     n各结点的二叉链表共有2n个链域,非空链域为n-1个,但其中的空链域却有n+1个。如下图所示。

  (除根结点以外,所有结点都有一共指向它的结点,所有非空链域为n-1,空链域为n+1)

  因此,提出了一种方法,利用原来的空链域存放指针,指向树中其他结点。这种指针称为线索。

    记ptr指向二叉链表中的一个结点,以下是建立线索的规则:

    (1)如果ptr->lchild为空,则存放指向中序遍历序列中该结点的前驱结点。这个结点称为ptr的中序前驱;

    (2)如果ptr->rchild为空,则存放指向中序遍历序列中该结点的后继结点。这个结点称为ptr的中序后继;

  显然,在决定lchild是指向左孩子还是前驱,rchild是指向右孩子还是后继,需要一个区分标志的。因此,我们在每个结点再增设两个标志域ltag和rtag,注意ltag和rtag只是区分0或1数字的布尔型变量,其占用内存空间要小于像lchild和rchild的指针变量。结点结构如下所示。

    其中:

    (1)ltag=0    时指向该结点的左孩子,为1时指向该结点的前驱

    (2)rtag=0   时指向该结点的右孩子,为1时指向该结点的后继

    (3)因此对于上图的二叉链表图可以修改为下图下的样子。

  

二、线索二叉树结构实现

  存储结构

typedef char DataType;
typedef enum{Link, Thread}PointerTag;    //Link = 0表示指向左右孩子指针;Thread = 1表示指向前驱或后继的线索
struct BitNode{
    DataType data;
    BitNode *lchild, *rchild;
    PointerTag ltag;
    PointerTag rtag;   
};
typedef BitNode* BitTree;
 中序遍历线索化
BitTree pre;
void InThreading(BitTree p){
    if(p){
        InThreading(p->lchild);//递归左子树线索化
        if (!p->lchild)//没有左孩子
        {
           p->ltag= Thread;//前驱线索
           p->lchild=pre;//左孩子指向前驱
        }
        if (!p->rchild)//没有右孩子
        {
           pre->rtag= Thread;//后继线索
           pre->rchild=p;//前驱右孩子指向后继
        }
        pre = p;
        InThreading(p->rchild);
    }
}
中序遍历二叉线索树表示二叉树t
int InOrderThraverse_Thr(BiTree t)
{
    BiTree p;
    p=t->lchild;                               //p指向根结点
    while(p!= t)                               //空树或遍历结束时p == t
    {
        while(p->ltag == Link)       //当ltag = 0时循环到中序序列的第一个结点
        {
            p = p->lchild;
        }
        cout<<p->data<<" ";     //显示结点数据,可以更改为其他对结点的操作
        while(p->rtag == Thread && p->rchild != t)
        {
            p = p->rchild;
            cout<<p->data<<" "; 
        }
        p = p->rchild;                         //p进入其右子树
    }
 
    return 0;
}

 

posted @ 2020-06-03 19:28  图神经网络  阅读(162)  评论(0编辑  收藏  举报
Live2D