线索二叉树
来源:互联网 发布:免费宠物店收银软件 编辑:程序博客网 时间:2024/06/05 20:16
线索二叉树方便了寻找前驱和后继
如何构造前面那棵二叉树的中序线索二叉树呢?假定线索二叉树采用链式存储结构,也就是要构造这棵二叉树的中序线索链表。
第一步:首先为二叉树中的每个结点都建立一个BiThrNode类型的结点,若某结点有左孩子,就令其左指针域指向左孩子结点,否则,就暂时让它为空;若某结点有右孩子,就令其右指针域指向右孩子结点,否则,就暂时让它为空。
第二步:为了便于对线索链表进行操作,和单链表一样,为二叉树的线索链表也增加一个头结点,并规定:头结点的左指针域指向二叉树的根结点,即头结点的左指针域是一个指针;头结点的右指针域指向中序列中的最后一个结点,即头结点的右指针域是一个线索,暂时令其为空。再令,若二叉树遍历序列中的第一个结点的左指针域为空,则让其指向线索链表的头结点,即把头结点看成是第一个结点的直接前驱;若二叉树遍历序列中的最后一个结点的右指针域为空,则也让其指向线索链表的头结点,即把头结点看成是最后一个结点的直接后继; 总之一句话,将头结点看成是第一个结点的直接前驱,同样看成是最后一个结点的直接后继。
第三步:若某结点的左指针域为指针,则令左标志为0,若某结点的右指针域为指针,则令右标志为0。反之,若某结点的左指针域为空,即将来成为线索,则令左标志为1,若某结点的右指针域为空,即将来成为线索,则令右标志为1。
第四步:按照中序遍历序列中结点的次序关系和第二步中的规定修改空指针,使其指向它的前驱结点或后继结点。
再来看一下上述二叉树的先序线索链表和后续线索链表的构造过程。
这里需要特别注意的是,若二叉树为空,则它对应的线索链表中只含有一个头结点,且规定头结点的左指针域指向其自身,即左指针域仍为指针;右指针域为空,即右指针域仍为线索,且在空线索链表中,右线索也指向头结点自身。空二叉树对应的线索链表如下所示。
<span style="font-size:14px;">//0 为link,1为thread#include <iostream>#include <stdlib.h>using namespace std;typedef struct node{ char data; struct node* lchild; struct node* rchild; int ltag,rtag;}bitnode,*bitree;void create(bitree &bt){ char data; cin>>data; if(data=='#') bt=NULL; else { bt=(bitree)malloc(sizeof(bitnode)); bt->data=data; create(bt->lchild); create(bt->rchild); }}void inthread(bitree &bt,bitree &pre)//二叉树中序线索化{ bitree &p=bt; if(p!=NULL) { inthread(p->lchild,pre); if(p->lchild==NULL) { p->ltag=1; p->lchild=pre; } else p->ltag=0; if(pre->rchild==NULL) { pre->rtag=1; pre->rchild=p; } else pre->rtag=0; pre=p; inthread(p->rchild,pre); }}void Inorderthread(bitree &bt){ bitree head,pre; head=(bitree)malloc(sizeof(bitnode));//对头结点进行初始化 head->ltag=0; head->rtag=1; head->rchild=head; if(bt==NULL)//如果是空树则左指针回指 head->lchild=head; else { head->lchild=bt; pre=head; inthread(bt,pre);//pre为最后一个结点 pre->rtag=1;//对最后一个结点初始化 pre->rchild=head; head->rchild=pre; head->rtag=1; } bt=head;//使bt指向头结点}/*******************************//*若p结点的右子树为空,则返回p结点右线索指向的结点 即p->rchild;/*若p结点的右子树不为空,则p的后继一定是p的右子树中序遍历的第一个结点/******************************/bitree getnext(bitree bt){ bitree q; if(bt->rtag==1)//如果求的该结点有右线索则直接返回右线索指向的结点 return bt->rchild; else { q=bt->rchild;//否则q为右子树根结点 while(q->ltag==0)//一直到当q结点的左子树的最下面 { q=q->lchild; } return q; }}bitree find(bitree &bt,char e){ bitree p; if(bt==NULL) return NULL; if(bt->data==e) return bt; p=find(bt->lchild,e); if(p!=NULL && p->data==e) return p; p=find(bt->rchild,e); if(p!=NULL && p->data==e) return p; return NULL;}void inthreadtraverse(bitree bt){ bitree p=bt->lchild;//p为根结点 while(p!=bt)//当p结点不为头结点的时候 { while(p->ltag==0)//一只寻找到左子树的最左边的结点使p指向中序遍历最左边的结点 { p=p->lchild; } cout<<p->data;//输出该结点的值 while(p->rtag==1 && p->rchild!=bt)//当该结点有右线索,且右线索不是头结点的时候 { p=p->rchild;//一值往右遍 cout<<p->data;//输出 } //当p所指结点的rchild指向的是孩子结点而不是线索时,p的后继应该是其右子树的最左下的结点,即遍历其右子树时访问的第一个节点 p=p->rchild; }}int main(){ bitree bt,p; create(bt); //bt=bt->lchild; //cout<<bt->data p=find(bt,'G'); Inorderthread(bt); p=getnext(p); cout<<p->data;}</span>
- 线索二叉树 --->树
- 线索二叉树算法
- C#线索二叉树
- 线索二叉树
- C#线索二叉树
- 线索二叉树
- 线索二叉树
- 线索化二叉树
- 线索二叉树
- C#线索二叉树
- C#线索二叉树
- 线索二叉树
- 线索二叉树实例
- 线索二叉树
- 线索二叉树算法
- C++线索二叉树
- 线索二叉树
- 线索二叉树实现
- tomcat 的http和ajp协议
- Android文件存储之SDcard
- 小白日记5:kali渗透测试之被动信息收集(四)--theHarvester,metagoofil,meltag,个人专属密码字典--CUPP
- Java IO深入理解
- 排序算法之冒泡排序
- 线索二叉树
- 【iOS知识学习】_int、NSInteger、NSUInteger、NSNumber的区别和联系
- POJ 3107树的重心
- 自白初衷
- Valid Perfect Square
- mybatis 原始dao开发和mapper代理开发的比较
- Leetcode 242. Valid Anagram
- CCF-201312-3-最大的矩形
- PAT 1026. Table Tennis (30)(待修改)