[数据结构]第六章-树和二叉树(读书笔记3)

来源:互联网 发布:windows gif 录制 编辑:程序博客网 时间:2024/06/06 00:16

线索二叉树
二叉树遍历的缺点:当以二叉树链表作为存储结构时,只能找到结点的左右孩子信息,而不能直接得到结点在任一序列中的前驱和后继信息,这种信息只有在遍历的动态过程中才能得到。
如何保存这种在遍历过程中得到的信息呢?一个最简单的办法是在每个结点上增加两个指针域fwd和bkwd,分别指示结点在任一次序遍历时得到的前驱和后继信息。
二叉链表作为二叉树的存储结构,叫做线索链表,其中指向结点前驱和后继的指针,叫做线索。加上线索的二叉树称之为线索二叉树(Threaded Binary Tree)。对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化。
线索二叉树通过设置LTAG,RTAG标志,并事先线索化来提高整个二叉树的遍历速度,是个典型的牺牲空间来提升速度的例子。线索二叉树方便查找一个结点在访问次序上的前后邻居。
LTag = 0 lchild域指示结点的左孩子
LTag = 1 lchild域指示结点的前驱
RTag = 0 lchild域指示结点的右孩子
RTag = 1 lchild域指示结点的后继
在线索树上进行遍历,只要先找到序列中结点,然后依次找结点后继直至其后继为空时为止。
根据中序遍历的规律可知,结点的后继应是遍历其右子树时访问的第一个结点。即右子树中最左下的结点。在中序线索二叉树上遍历二叉树,虽则时间复杂度亦为O(n),但常数因子要小很多,且不需要设栈。因此,若在某程序中所用二叉树需经常遍历或查找结点在遍历所得线性序列中的前驱和后继,则应采用线索链表作存储结构。
由于线索化的实质是将二叉链表中的空指针改为指向前驱或后继的线索,而前驱或后继的信息只有在遍历时才能得到,因此线索化的过程即为在遍历的过程中修改空指针的过程。

/*Link == 0 指针 Thread == 1 线索*/typedef enum PointTag {Link,Thread}PointerTag;typedef struct BiThrNode{TElemType data;struct BiThrNode *lchild, *rchild;/*左右孩子指针*/PointerTagLTag,RTag;/*左右标志*/}BiThrNode,*BiThrTree;Status CreateBiThrTree(BiThrTree *T){ /* 按先序输入二叉线索树中结点的值,构造二叉线索树T *//* 0(整型)/空格(字符型)表示空结点 */TElemType h;#if CHARscanf("%c",&h);#elsescanf("%d",&h);#endifif(h == NIL){*T=NULL;}else{*T=(BiThrTree)malloc(sizeof(BiThrNode));if(!*T){exit(OVERFLOW);}(*T)->data = h; /* 生成根结点(先序) */CreateBiThrTree(&(*T)->lchild); /* 递归构造左子树 */if((*T)->lchild){ /* 有左孩子 */(*T)->LTag = Link;}CreateBiThrTree(&(*T)->rchild); /* 递归构造右子树 */if((*T)->rchild){ /* 有右孩子 */(*T)->RTag = Link;}}return OK;}BiThrTree pre; /* 全局变量,始终指向刚刚访问过的结点 */void InThreading(BiThrTree p){if (p){/* 中序遍历进行中序线索化。算法6.7 */InThreading(p->lchild);//左子树线索化if(!p->lchild){//前驱线索p->LTag = Thread;p->lchild = pre;}if(!pre->rchild){//后继线索pre->RTag = Thread;pre->rchild = p;}pre = p; /* 保持pre指向p的前驱 */InThreading(p->rchild);//右子树线索化}}Status InOrderThreading(BiThrTree Thrt, BiThrTree T){//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点if(!(Thrt = (BiThrTree)malloc(sizeof(BiThrTree)) )){exit(OVERFLOW);}//建头结点Thrt->LTag = Link;Thrt->RTag = Thread;//右指针回指Thrt->rchild = Thrt;//若二叉树空,则左指针回指if (T == NULL){Thrt->lchild = Thrt;}else{Thrt->lchild = T;pre = Thrt;InThreading(T);//最后一个结点线索化pre->rchild = Thrt;pre->RTag = Thread;Thrt->rchild = pre;}return OK;}Status InOrderTraverse_Thr(BiThrTree T,Status(*Visit)(TElemType)){/* 中序遍历二叉线索树T(头结点)的非递归算法。算法6.5 */BiThrTree p;//p指向根结点p = T->lchild;while(p != T){//空树或遍历结束时,p==Twhile(p->LTag == Link){p = p->lchild;}if(!Visit(p->data)){return ERROR;}while (p->RTag == Thread && p->rchild != T){p = p->rchild;Visit(p->data);//访问后继结点}p = p->rchild;}return OK;}Status vi(TElemType c){#if CHARprintf("%c ",c);#elseprintf("%d ",c);#endifreturn OK;}int _tmain(int argc, _TCHAR* argv[]){ BiThrTree H = NULL,T;#if CHARprintf("请按先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n");#elseprintf("请按先序输入二叉树(如:1 2 0 0 0表示1为根结点,2为左子树的二叉树)\n");#endifCreateBiThrTree(&T); /* 按先序产生二叉树 */InOrderThreading(H,T); /* 中序遍历,并中序线索化二叉树 */ printf("中序遍历(输出)二叉线索树:\n");InOrderTraverse_Thr(T,vi); /* 中序遍历(输出)二叉线索树 */printf("\n");return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买家旺旺被限制怎么办 淘宝支付不了了怎么办 手机图标变黑了怎么办 商品没有支付宝怎么办 金立s8热点打不开怎么办 淘宝店铺异常2怎么办 付款付错了怎么办 手机淘宝太卡怎么办 卖家不同意退货怎么办 游戏退出无响应怎么办 手机淘宝购物车打不开怎么办 淘宝店铺没有访客怎么办 淘宝店铺0流量怎么办 微信经常封号怎么办 网上拍卖堂违约怎么办 dnf4开组队制裁怎么办 红酒木塞丢了怎么办 红酒塞子进去了怎么办 淘金币即将过期怎么办 淘金币过期怎么办2018 换详情排名下降怎么办 长城宽带不用了怎么办 快递到了想退货怎么办 淘宝退货商家拒收怎么办 淘宝运费险失败怎么办 忘记购买运费险怎么办 咸鱼买家申请退款怎么办 熟猪肉有点变味怎么办 和领导意见不一致怎么办 骑手提前点送达怎么办 ubuntu安装报错怎么办 液相色谱两峰分不开怎么办 液相色谱柱老堵怎么办? 没有装usb驱动怎么办 ipad速度越来越慢怎么办 美萍管理软件打不开怎么办 小米4开机黑屏怎么办 小米电脑死机了怎么办 小米8手机死机怎么办 oppa7开不了机怎么办 oppo手机wlan打不开怎么办