数据结构之树和二叉树(三)

树与二叉树

   一、关系:

      1)二叉树是树的特殊一种。(于此,你会想,要是把树转化成二叉树那多好了)。

       由下图可知树转换为二叉树是可能的

       (这里引入二叉树的节点,以便对下图的理解)

typedefstructnode
{ DataType data;
structnode *fch, *nsib;
}CSNode,*CSTree;


       

   二、树与二叉树的转化

       步骤      

      �C加线:在兄弟之间加一连线

       �C抹线:对每个结点,除了其左孩子外,

       去除其与其余孩子之间的关系

       �C旋转:以树的根结点为轴心,将整树顺

       时针转45°

       

  三、森林转化为二叉树

   步骤:

   �C 将各棵树分别转换成二叉树

   �C 将每棵树的根结点用线相连

   �C 以第一棵树根结点为二叉树的根,再以根结点为轴心,顺时针旋转,构成二叉树

                 

    四、二叉树转换成树(实际当中或多或少可能会用到本转化)

   �C加线:若p结点是双亲结点的左孩子,则

    -将p的右孩子,右孩子的右孩子,……沿分支找到的所有右孩子,都与p的双亲用线连起来

   �C抹线:抹掉原二叉树中双亲与右孩子之间的连线

   �C调整:将结点按层次排列,形成树结构

   

   线索二叉树

   简单链表的缺点:

    一,浪费空间

     二,浪费时间

   单链表有时并不能满足设计的程序某些要求,于是发明了双向链表来弥补,线索二叉树也是在需求中被创造的。

   线索二叉树的节点如下

   

   ltag为0时指向该结点的左孩子,为1时指向该结点的前驱。rtag为0时指向该结点的右孩子,为1时指向该结点的后继。

  特点:

   除第一个结点外每个结点有且仅有一个直接前驱结点;

   除最后一个结点外每一个结点有且仅有一个直接后继结点。

   定义:这些指向直接前驱结点和指向直接后续结点的指针被称为线索(Thread),加了线    索的二叉树称为线索二叉树。

 

    以中序(左中右)线索化遍历为例

   定义变量

   先定义节点全局变量pre

   定义当前节点T

   变量变化:

   left为null时指向前驱(代码表现为left=pre);

   right为null时指向后继(代码表现为right = T)

   pre,当且left为null时

   线索化如下

  1)先一直往左边线索化,直到left为null时,见下图

   

   2)、pre第一次变化的时候

 


2)最后得到的是,可以结合代码来看

   


五、线索化二叉树的代码实现

   假设有下列二叉树

       

       先序遍历结果是abc_ _d_ _e_f_ _

       代码实现如下



#include<stdio.h>
#include<stdlib.h>
#define OK 0
typedef int Status;
typedef char ElemType;
//Link;present a point towords left or right child
//Thread present the previous Thread of left or right child
typedef enum {Link, Thread} PointerTag;
typedef struct BiThrNode
{
    ElemType data;
    struct BiThrNode *lchild, *rchild;
    PointerTag ltag;
    PointerTag rtag;
}BiThrNode, *BiThrTree;
//全局变量保存刚访问过的节点
BiThrTree pre;
Status CreateBiThrTree(BiThrTree *T)
{
ElemType c;
scanf("%c", &c);//先序赋值abc_ _d_ _e_f_ _
if(c == ' ')
{
    *T= NULL;
}
else
{
*T = (BiThrTree)malloc(sizeof(BiThrNode));
(*T)->data = c;
(*T)->ltag = Link;
(*T)->rtag = Link;
CreateBiThrTree(&(*T)->lchild);
CreateBiThrTree(&(*T)->rchild);
}
return OK;
}
//mid threading
Status InThreading(BiThrTree T)
{
if(T)//
{
InThreading((T->lchild));//线索二叉树理解关键在这,递归调用一直往左边寻找空节点,见图1
if(!T->lchild){//直到空时
T->ltag = Thread;//置T.lag = Thread,第一次lchild为空时见图一
T->lchild = pre;
}
if(!pre->rchild)//右序遍历
{
pre->rtag = Thread;
pre->rchild = T;
}
pre = T;//pre第一次变值看图二
InThreading(T->rchild);
}
return OK;
}
Status InOrderThreading(BiThrTree *p, BiThrTree T)//
{
*p = (BiThrTree)malloc(sizeof(BiThrNode));
(*p)->ltag = Link;
(*p)->rtag = Thread;
(*p)->rchild = *p;
if(!T)
{
    (*p)->lchild = *p;
}else
{
(*p)->lchild = T;
pre = *p;
InThreading(T);
pre->rchild = *p;
pre->rtag = Thread;
(*p)->rchild = pre;
}
return OK;
}
void visit(ElemType e){
    printf("%c", e);
}
//T为头指针
Status InOrderThraverse(BiThrTree T)
{
BiThrTree p;
p = T->lchild;
    while(p != T)
    {
        while( p->ltag == Link)
        {
        p = p->lchild;
        }
        visit(p->data);
        while(p->rtag == Thread && p->rchild!= T)
        {
        p = p->rchild;
        visit(p->data);
        }
        p = p->rchild;
    }
    return OK;
}
int main()
{
    BiThrTree p,T = NULL;
    CreateBiThrTree(&T);//先序赋值abc_ _d_ _e_f_ _
    InOrderThreading(&p, T);
    printf("the mid thread result is:");
    InOrderThraverse(p);
    printf("\n");
    return 0;  
}


六、知识回顾

   树与二叉树的转化

   森林与二叉树的转化

   二叉树转化为森林

   线索化二叉树

   线索化的代码实现

你可能感兴趣的:(数据结构,二叉树,线索二叉树,树与二叉树的转化)