二叉树的线索化

来源:互联网 发布:费玉清网络综艺节目 编辑:程序博客网 时间:2024/06/14 02:08

当二叉树使用链表表示时,用左右两个孩子指针可以找到左右孩子信息。我们可以用先序、中序、后序遍历二叉树,不同的遍历得到不同排列顺序的结点信息。只有在遍历的过程中才能得到某一结点的前驱与后继结点。
在n个结点的二叉树中,有2n个指针域,根节点不用指针域,其他(n-1)个结点只用了(n-1)个指针域,还有(n+1)个指针域空着没用,我们可以利用者空着的指针域来记录某种遍历下结点的前驱与后继。为了区分某个结点的指针域是指向孩子还是指向前驱/后继,要给结点添加的两个指针域添加标志,定义如下:

struct Node{      Node(int d):data(d),left(NULL),right(NULL),ltag(false),rtag(false){}       int data;      Node *left;      Node *right;bool ltag;bool rtag;};

当ltag=false时,left指向左孩子;当ltag=true时,left指向其前驱
当rtag=false是,right指向其右孩子;当rtag=true时,right指向其后继。
将一颗二叉树n+1个空指针域添加前驱或后继的过程就是线索话二叉树的过程。显然结点的前驱与后继只有在遍历的过程中才能得到,线索话二叉树的过程也就是遍历二叉树的过程。二叉树线索后,就可以通过左右孩子指针直接找到其前驱与后继,以中序线索话为例,当二叉树中序线索话后,
1、找某结点的前驱:
如果该结点的ltag=true,那么left指向的结点就是其前驱结点
如果该结点的ltag=false,那么该结点左子树最右边的结点就是其前驱结点。
2、找某结点后继
如果该结点的rtag=true,那么rtag指向的结点就是其后继结点
如果该结点的rtag=false,那个该结点的右子树的最左边的结点就是其后继结点。
二叉树线索话过程就是遍历过程,递归线索话时,需要一个全局变量来指向上一次遍历的结点(前驱结点)

Node *pre=NULL;//全局变量 ,刚刚遍历的结点 void BinTree::inorderThreading(Node *r)//中序线索话 {if(r==NULL)return;inorderThreading(r->left);//递归线索话左子树 if(r->left==NULL)//如果左子树为空,则定义其前驱 {r->ltag=true;r->left=pre;}if(r->right==NULL)//右子树为空,先标记其指向后继,后继结点在下一次遍历才能得到,这里只是先标记 r->rtag=true; if(pre!=NULL&&pre->rtag==true)//上次遍历的结点右子树指针被标记了,这次遍历的就是其后继 pre->right=r;pre=r;//相当于遍历当前结点inorderThreading(r->right);//线索话其右子树 }
线索话后,如果要销毁二叉树,destroy函数要做点修改,当左右指针指向左右孩子时才可以递归销毁

//销毁树 void BinTree::destroy(Node *r){if(r==NULL)return;if(r->ltag==false)destroy(r->left);if(r->rtag==false)destroy(r->right); delete r; r=NULL;}



0 0
原创粉丝点击