4.线索二叉树
4.1 线索二叉树概念
-
目的:为了快速查找结点的前驱和后继。
-
原理推导:
∵ 空指针数量= 2 n 2 + n 1 2n_2+n_1 2n2+n1,又 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
∴ n 0 + n 1 + n 2 + 1 = n + 1 n_0+n_1+n_2+1=n+1 n0+n1+n2+1=n+1,即空指针数量等于结点总数
∴ 可以利用空指针来存储该结点的前驱后继。
-
方法:
在结点结构中多加两个int型标志位
ltag
和rtag
。若
标志位=0
,lchild
和rchild
指针分别指向左右孩子;若
标志位=1
,lchild
和rchild
指针分别指向前后驱。 -
定义
//在原二叉树链式存储的基础上,添加左右线索标志位 typedef struct ThreadNode{ ElemType data; struct ThreadNode *lchild,*rchild; int ltag,rtag;//左右线索标志位 }ThreadNode,*ThreadTree;
4.2 中序线索二叉树
-
二叉树线索化:
将二叉链表中的空指针改为前后继指针。
而前后继需要遍历二叉树后才能得到。
因此 二叉树线索化实质是要遍历一次二叉树。
-
存储示意图:
-
代码
//中序线索化 void InThread(ThreadTree p,ThreadTree &pre){ if(p!=NULL){ InThread(p->lchild,pre);//递归,线索化左子树 //左子树为空,建立前驱线索 if(p->lchild==NULL){ p->lchild=pre; p->ltag=1; } //建立前驱结点的后继线索 if(pre!=NULL&&pre->rchild==NULL){ pre->rchild=p; pre->rtag=1; } pre=p;//标记当前结点成为刚刚访问过的结点 InThread(p->rchild,pre); //递归,线索化右子树 } } //中序线索化二叉树T void CreateInThread(ThreadTree T){ ThreadTree pre=NULL; //非空二叉树,线索化 if(T!=NULL){ InThread(T,pre);//线索化二叉树 pre->rchild=NULL;//处理遍历的最后一个结点 pre->rtag=1; } }
4.3 先序线索二叉树
-
存储示意图
-
代码
//先序线索化 void PreThread(ThreadTree p,ThreadTree &pre){ //左子树为空,建立前驱线索 if(p!=NULL){ p->lchild=pre; p->ltag=1; } //建立前驱结点的后继线索 if(pre!=NULL&&pre->rchild==NULL){ pre->rchild=p; pre->rtag=1; } pre=p; if(p->ltag==0){ PreThread(p->lchild,pre); } PreThread(p->rchild,pre); } //先序线索化二叉树T void CreatePreThread(TreadTree T){ ThreadTree pre=NULL; if(T!=NULL){ PreThread(T,pre); if(pre->rchild==NULL) pre->rtag=1; } }
4.4 后序线索二叉树
-
存储示意图
-
代码
//后序线索化 void PostThread(ThreadTree p,ThreadTree &pre){ if(p!=NULL){ PostThread(p->lchild,pre);//递归,线索化左子树 PostThread(p->rchild,pre);//递归,线索化右子树 //左子树为空,建立前驱线索 if(p->lchild==NULL){ p->lchild=pre; p->ltag=1; } if(pre!=NULL&&pre->rchild==NULL){ pre->rchild=p; pre->rtag=1; } pre=p; } } //后序线索化二叉树T void CreatePostThread(ThreadTree T){ ThreadTree pre=NULL; if(T!=NULL){ PostThread(T,pre); if(pre->rchild==NULL) pre->rtag=1; } }