一、线索二叉树的构造
#include <stdio.h> //定义线索二叉树结点 typedef struct ThreadNode { int data; //数据域存放二叉树数据 ThreadNode * lchild,*rchild; //左右孩子 int ltag,rtag; //左右孩子标志位 }ThreadNode,* ThreadTree; ThreadNode * pre; //全局变量,当前结点的前驱结点
二、构造并中序线索化
//访问某一个树结点同时进行线索化 void Visit(ThreadNode * p) { if(p->lchild==NULL) { p->lchild=pre; p->ltag=1; } if(pre!=NULl&&pre->rchild==NULL) { pre->rchild=p; //建立前驱结点的后继线索 pre->rtag=1; } pre=p; //把pre置为当前结点,当下一次调用visit时访问的pre就是当前结点(下一次遍历的前驱) } //二叉树中序遍历(并调用Visit进行线索化) void InThread(ThreadTree T) { if(T!=NULL) { InThread(T->lchild); Visit(T); InThread(T->rchild); } } void CreateInThread(ThreadTree T) { pre=NULL; if(T!=NULL) { InThread(T); if(pre->rchild==NULL) pre->rtag=1; //对最后一个结点进行特殊处理 } }
三、构造并先序线索化(构造代码同上)
//二叉树先序遍历(并调用Visit进行线索化) void InThread(ThreadTree T) { if(T!=NULL) { Visit(T); if(T->LTag==0)InThread(T->lchild); //!!!注意此处的判断条件,因为先序遍历访问顺序是根左右,如果根线索化了,无论根有没有左孩子,lchild都有指向,因此必须加此判断条件,判断其到底有没有左孩子 InThread(T->rchild); } }
四、线索二叉树的遍历
(1)中序遍历
//找到以p为根的子树中第一个被中序遍历的结点,即最左下的那个结点 ThreadNode * FirstNode(ThreadNode * p) { while(p->ltag==0) p=p->lchild; return p; } //找到某个结点的后继节点 ThreadNode * NextNode(ThreadNode * p) { if(p->rtag==1) return p->rchild; else if(p->rchild==0) return FirstNode(p->rchild); //返回右子树最左下的那个结点 } void Inorder(ThreadTree * T) { for(ThreadNode * p=FirstNode(T);p!=NULL;p=NextNode(p)) //先找到第一个结点,然后不断的找其后继 visit(p); }
(2)逆向中序遍历:从最后一个结点开始不断遍历其前驱即可。