由于有了结点的前驱和后继信息,线索二叉树的遍历和指定次序下查找结点的前驱和后继算法都变得简单,线索二叉树的遍历不需要设栈,避免了频繁的进栈、出栈,因此在时间和空间上都较遍历二叉树节省。
因此,若需要经常查找结点在所遍历线性序列中的前驱和后继,则采用线索链表作为存储结构。
1)中序线索二叉树
1. 查找p的前驱:查左线索;若无左线索,结点的前驱是遍历左子树时访问的最后一个结点。
2. 查找p的后继:查右线索;若无右线索,结点的后继是遍历右子树时访问的第一个结点。
2)先序线索二叉树
1. 查找p的前驱:查左线索;若无左线索,结点的前驱是结点的双亲结点,或是先序遍历其双亲结点左子树时最后访问的结点。
2. 查找p的后继:查右线索;若无右线索,结点的后继必为结点的左子树(若存在)或右子树根结点。
3)后序线索二叉树
1. 查找p的前驱:查左线索;若无左线索,且无右线索时,结点的前驱是右子树根结点;若无左线索,但是有右线索时,结点的前驱是左子树根结点。
2. 查找p的后继,这种查找比较复杂,分4类情况讨论:
若p为二叉树的根结点,后继为空;
若p为右子树根结点,后继为双亲结点;
若p为左子树根结点,且无右兄弟,后继为双亲结点;
若p为左子树根结点,且有右兄弟,后继为后序遍历双亲结点右子树时访问的第一个结点。
由上述情况可知,在先序线索二叉树上找前驱和在后序线索二叉树上找后继都比较复杂。
遍历线索二叉树的时间复杂度为O(n),与递归或非递归遍历二叉链表一样,但前者的空间复杂度为O(1),而后者为O(n),因为遍历线索二叉树不需要栈。
/*----------遍历中序线索二叉树----------*/
void InOrderTraverse(ThBiTree t)
{/*t指向线索二叉树的头结点,而头结点的左指针指向二叉树的根结点*/
ThBinode *p = t->lchild; /*使p指向根结点*/
while(p != t) /*若线索二叉树不为空或遍历未结束*/
{
while(p->LTag == 0) p=p->lchild; /*沿左孩子往下,定位*/
cout<<p->data; /*访问左子树为空的结点*/
while(p->RTag == 1 && p->rchild != t) /*若有右线索,且右线索不为头结点*/
{
p = r->rchild;
cout<<p->data; /*沿右线索访问后继结点*/
}
p = p->rchild; /*转向p的右子树*/
}
}
感谢分享
强~~希望更多人更加努力