(2)线索二叉树结构实现
/*二叉树的二叉线索存储结构定义
* Link==0表示左右孩子指针
* Thread==1表示指向前驱或后驱的线索
*/
typedef eum {Link,Thread} PointerTag;
typedef struct BiThrNode /*二叉线索存储结点结构*/
{
TElemType data; //数据域:结点数据
struct BiThrNode *lchild,*rchild; //指针域:左右孩子指针
PointerTag LTag;
PointerTag RTag; //左右标志
}BiThrNode,*BiThrTree;
/*T指向头结点,头结点左键lchild指向根结点,头结点右链rchild指向中序遍历的最后一个结点 * 中序遍历二叉线索链表表示的二叉树T,时间复杂度为O(n)*/ Status InOrderTraverse_Thr(BiThTree T) { BiThrTree p; p=T->lchild; //p指向根结点 while(p != T) //空树或遍历结束时,p==T { while(p->LTag==Link) //当LTag==0时循环到中序序列第一个结点 p=p->lchild; printf("%c",p->data); //显示结点数据,可以更改为其他对结点操作 while(p->RTag == Thread && p->rchild !=T) { p=p->rchild; printf("%c",p->data); } p=p->rchild; //p进至其右子树根 } } 源码分析: (1) p=T->lchild;让p指向根结点开始遍历,如上图编号①所示; (2)while(p!=T):即循环直到图中的④的出现,此时意味着p指向了头结点,于是与T相等(T是指向头结点的指针),结束循环,否则一直循环下去去进行遍历操作; (3)while(p->LTag==Link) 循环,就是由A->B->D->H,此时H结点的LTag不是Link(就是不等于0),所以结束此循环并打印H; (4)while(p->RTag == Thread && p->rchild !=T),由于结点H的RTag==Thread(就是等于1),且不是指向头结点。因此打印H的后继D,之后因为D的RTag是Link,因此退出循环; (5)p=p->rchild,即p指向了结点D的右孩子。 .....................不断循环,直到打印出HDIBJEAFCG结束遍历操作。 总结:二叉树的线索化有利于节省空间和时间,在实际问题中,如果所用的二叉树需经常遍历或查找结点时需要某种遍历序列中的前驱和后继,那么采用线索二叉链表的存储结构是一个非常不错的选择。