线索二叉树_legend

来源:互联网 发布:stc12c5a32s2数据手册 编辑:程序博客网 时间:2024/05/22 10:53


线索二叉树:
(一)线索二叉树的概念:
 二叉树的遍历是对一个非线性化的结构进行线性化的过程,它使得每个节点(除了第一个节点和最后一个节点),在线性序列中有且只有一个前驱和后继。但二叉链表的结构只能得到一个节点的左孩子,右孩子,并不能得出前序后继的信息。
 n个节点的二叉树,有n+1个空的指针域,可以用这些空指针域来存放某种遍历下的前驱和后继节点指针,称为线索。
 在空的 左指针中存放前驱节点的指针称之为左线索,在空的右指针中存放后继节点的指针称为右线索。

(二)线索二叉树的目的:
二叉树的遍历就是讲所有节点排列在一个线性序列中,如果每次寻找某个节点在某种顺序下的直接前驱或后继都需要重新遍历一次二叉树,将十分低效。线索二叉树,就是将所有节点的前驱,后继直接存放在树中,方便再次寻找某节点的前驱,后继,可以快些。

(三)线索二叉树的类型定义:

typedef struct BTNode{
 int ltag,rtag;
 struct BTNode* lchild,*rchild;
 DataType data;
}ThreadNode;
ltag=0,则lchild表示该节点的左孩子指针;
ltag=1,则lchild表示该节点的前驱指针;
rtag=0,表示rchild为该节点的右孩子指针;
rtag=1,表示rchild为该节点的后继节点指针。

(四)线索二叉树的种类:

前序线索二叉树,中序线索二叉树,后序线索二叉树,层次线索二叉树;
如下图所示:

(五)线索二叉树的构造:

(1)中序线索二叉树的构造:
1)代码分析:

void createInThread(ThreadNode* root){
 //通过中序遍历建立中序线索二叉树
 ThreadNode* pre=NULL;
 if(root){

  inThread(root,pre);
  pre->rchild=NULL;//后序处理中序的最后一个节点
  pre->rtag=1;
 }

}
/*
若p为正在访问的节点,pre为刚刚访问的节点;
引用型参数pre;
基于中序遍历;
建立当前节点p的前驱节点pre;
*/
void inThread(ThreadNode* p ,ThreadNode* & pre){
 if(p){
  inThread(p->lchild,pre);//左子树线索化;
  if(p->lchild==NULL ){//建立当前节点p的前驱线索
  p->lchild=pre;
  p->ltag=1;
  }

  if(pre!=NULL && pre->rchild==NULL){//建立前驱节点的后继
  pre->rchild=p;
  pre->rtag=1;
  }
  pre=p;//当前节点处理完毕,更新pre
  inThread(p->lchild,pre);
 }

}
----
(2)前序线索二叉树的创建:
void createPreThread(ThreadNode* root){
 ThreadNode* pre=NULL;
 preThread(root,pre);
 pre->rtag=1;//处理前序遍历的最后一个节点
 pre->rchild=NULL;
}
/*
pre为引用型参数;
为当前节点p建立前驱
*/

void preThread(ThreadNode* p, ThreadNode* & pre){
 if(p!=NULL){
  if(p->lchild==NULL){//为当前节点p构造前驱
   p->ltag=1;
   p->lchild=pre;
  }

  if(pre!=NULL && NULL==pre->rchild){//为前驱节点pre构造后继
  pre->rtag=1;
  pre->rchild=p;
  }

  pre=p;//当前节点p处理完毕,更新pre
  preThread(p->lchild,pre);
  preThread(p->rchild,pre);

 }
}

---
(3)后序线索二叉树的创建:

---------------
(六)线索二叉树的遍历:
这种遍历不需要栈,因为二叉树隐含了前驱后继信息。
(1)中序线索二叉树的 遍历:
/*
求取以p为根节点的中序线索二叉树的中序序列下的第一个节点;
*/
ThreadNode* getFirst(ThreadNode* p){
 while(p->ltag==0)
 p=p->lchild;//最左下节点(不一定是叶子)
 return p;
}

/*
求取中序线索二叉树节点p的后继节点
*/
ThreadNode* getNext(ThreadNode* p){
 if(p->rtag==0)//如果有右子树,则返回右子树的最左下节点
 return getFirst(p->rchild);
 else return p->rchild;//没有右孩子,则返回后继节点。
}

/*获取以p为根节点的中序线索二叉树的最后一个节点*/
ThreadNode* getLast(ThreadNode* p){
 while(p->rtag==0)//获取p的最右下的节点(不一定是叶子)
 p=p->rchild; 
 return p;
}

/*获取中序线索二叉树中p节点的前驱节点*/
ThredadNode* getPrior(ThreadNode* p){
 if(0==p->ltag) //有左孩子,则返回左子树的最右下的节点。
 return getLast(p->lchild);
 else return p->lchild;//无左孩子,则返回直接前驱。
}

/*
遍历以root为根节点的中序线索二叉树
*/

void inOrderTraversal(ThreadNode* root){
 for(ThreadNode* p=getFirst(root); p!=NULL; p=getNext(p)){
  visit(p->data);
 }
}

----

(2)前序线索二叉树的遍历:

/*求以t为根的前序线索二叉树,求得节点pnode 的父节点*/

ThreadNode* getParent(ThreadNode* t,ThreadNode* pnode){
 
 if(NULL==t) return NULL;
 else if(t->lchild==pnode || t->rchild==t) return t;

 ThreadNode* parent=getParent(t->lchild,pnode);
 if(parent) return parent;
 else return getParent(t->rchild,pnode);
}

/*
以t为根节点的前序线索二叉树的第一个节点
*/

ThreadNode* getFirst(ThreadNode* t){
 
 return t;
}

/*
以t为根节点的前序线索二叉树的最后一个节点;
分析:若t的右子树非空,则前序最后一个节点一定是右子树上前序的最后一个节点,
若右子树为空,则前序最后一个节点就是左子树前序的最后一个节点。
若左右子树均为空,则自己就是最后一个节点。
*/

ThreadNode* getLast(ThreadNode* t){
 if(t!=NULL && t->rtag==0)//t的右子树非空
 getLast(t->rchild);

 else if(t!=NULL && t->ltag==0)//t的左子树非空
 getLast(t->lchild);

 else return t;
}

/*
以t为根节点的前序线索二叉树,pnode的下一个节点
*/
ThreadNode* next(ThreadNode* t, ThreadNode* pnode){
 
 if(pnode!=NULL && pnode->ltag==0)
 //pnode的左孩子非空,则返回左孩子
 return pnode->lchild;

 else if(pnode!=NULL && pnode->ltag==1)//左子树为空
 return pnode->rchild;
 //pnode->rtag==1或0,则都是后继,因为==1,为直接后继,==0,为右孩子
}


/*
以t为根节点的前序线索二叉树,求得pnode节点的前驱;
不过在线索二叉树中,求取前驱后继,好像不需要根节点t。
*/

ThreadNode* prior(ThreadNode* t , ThreadNode* pnode){
 if(pnode!=NULL && 1==pnode->ltag)//Pnode左孩子为空,左孩子为直接前驱
 return  pnode->lchild;

 else if(pnode!=NULL && 0=pnode->ltag)//拥有左孩子
 {
  ThreadNode* parent=getParent(t,pnode);//获取pnode的 父节点
   if(parent->lchild==pnode)//pnode为parent的左孩子
   return parent;
   else if (parent->rchild==pnode){//pnode为parent的右孩子,
    return getLast(parent->lchild);//父节点左子树的最后一个节点。
   }
 }
}

/*
遍历前序线索二叉树
*/

void preTraversal(ThreadNode* root){
 
 for(ThreadNode* pnode=getFirst(root);pnode!=NULL; pnode=next(root,pnode)){
  visit(pnode);
 }
}
------

0 0
原创粉丝点击