6.3线索二叉树(二叉树的线索化)
问题引入:以二叉链表作为存储结构时,只能得到结点的左、右孩子的信息,不能得到直接前驱、后继的信息。
问题解决:将二叉树线索化。
实现原理:n个结点的二叉树具有n+1个空指针域,利用这些空指针域存储结点的前驱、后继信息。
实质:线索化的实质是将二叉链表中的空指针改为指向前驱、后继的线索。
(1)二叉树的存储表示
enum {link,thread};//link=0; thread=1; typedef struct bintree { char data; struct bintree *lchild, *rchild; int ltag,rtag;//标志域。指示 指针或线索 }BiNode, *BiTree;
(2)二叉树的创建
见6.1二叉树的创建章节。
(3)中序线索化 及 遍历(注意注释内容)
BiTree inorder_threading(BiTree thrt,BiTree t) { thrt = (BiTree )malloc(len);//建立头指针 if(!thrt) exit(0); thrt->rtag = thread;//右指针回指 thrt->rchild = thrt; thrt->ltag = link; if(!t)//若二叉树空,左指针回指 thrt->lchild = thrt; else { thrt->lchild = t; pre = thrt; in_threading(t);//中序遍历进行中序线索化 pre->rtag = thread;//最后一个节点线索化 pre->rchild = thrt; thrt->rchild = pre; } return thrt; } void in_threading(BiTree p) { if(p) { in_threading(p -> lchild);//左子树线索化 if(! p->lchild)//前驱线索 { p->ltag = thread; p->lchild = pre; } if(! pre->rchild)//后继线索 { pre->rtag = thread; pre->rchild = p; } pre = p;//保持pre指向 p 的前驱 in_threading(p->rchild);//右子树线索化 } }
void inorder_traverse(BiTree thrt) { BiTree p = thrt->lchild; while(p != thrt)//空树或遍历结束时,p==thrt { while(p->ltag == link) { p = p->lchild; } printf("%c ",p->data); if(p->rtag == thread && p->rchild != thrt) { p = p->rchild; printf("%c ",p->data); } p = p->rchild; } }
(4)先序线索化 及 遍历
BiTree preorder_threading(BiTree thrt,BiTree t) { thrt = (BiTree )malloc(len); if(! thrt) exit(0); thrt -> rtag = thread; thrt -> rchild = thrt; thrt -> ltag = link; if(!t) thrt -> lchild = thrt; else { thrt -> lchild = t; pre = thrt; pre_threading(t); pre -> rtag = thread; pre -> rchild = thrt; thrt -> rchild = pre; } return thrt; } void pre_threading(BiTree p) { if(p) { if(! p->lchild) { p -> ltag = thread; p -> lchild = pre; } if(!p -> rchild) p -> rtag = thread; if(pre && pre->rtag == thread) pre -> rchild = p; pre = p; if(p->ltag == link) pre_threading(p -> lchild); if(p->rtag == link) pre_threading(p -> rchild); } }
void preorder_traverse(BiTree thrt) { BiTree p = thrt -> lchild; printf("%c ",p->data); while(p->rchild != thrt) { if(p->ltag == link) p = p->lchild; else p = p->rchild; printf("%c ",p->data); } }
(5)后序线索化 及 遍历
BiTree postorder_threading(BiTree thrt,BiTree t) { thrt = (BiTree )malloc(len); if(! thrt) exit(0); thrt -> rtag = thread; thrt -> rchild = thrt; thrt -> ltag = link; if(!t) thrt -> lchild = thrt; else { thrt -> lchild = t; pre = thrt; post_threading(t); pre -> rtag = thread; pre -> rchild = thrt; thrt -> rchild = pre; } return thrt; } void post_threading(BiTree p) { if(p) { post_threading(p->lchild); //左子树线索化 post_threading(p->rchild); //右子树线索化 if(!p->lchild) { p->ltag=thread; p->lchild=pre; } if(!pre->rchild) { pre->rtag=thread; pre->rchild=p; } pre=p; } }
void postorder_traverse(BiTree thrt) { BiTree p = thrt; while(p->ltag==link||p->rtag==link) //有左孩子先访问左孩子,没有左孩子先访问右孩子 { while(p->ltag==link) p=p->lchild; if(p->rtag==link) //访问左孩子为空的结点的右孩子 p=p->rchild; } printf("%c ",p->data); while(p!=T) //p不为根结点 { if(p->rtag==link) //若p是有兄弟的左孩子 { if(pre->rtag==thread||p==pre->rchild) //若p是双亲的右孩子或是独生左孩子,则后继为双亲 p=pre; else { p=pre->rchild; //后继为双亲的右子树上按照后序遍历访问的第一个结点。 while(p->ltag==link||p->rtag==link) { while(p->ltag==link) p=p->lchild; if(p->rtag==link) p=p->rchild; } } } else p=p->rchild; //p指向后继 printf("%c ",p->data); } }
(6)总程序源代码(.c)
/* 样例输入: abc##de#g##f### */ # include <stdio.h> # include <stdlib.h> # define len (sizeof(BiNode)) # define OK 1 enum {link,thread}; typedef struct bintree { char data; struct bintree *lchild, *rchild; int ltag,rtag; }BiNode, *BiTree; BiTree T, thrt, pre; int bintree_creat(BiTree *q); void welcome(BiTree t); BiTree preorder_threading(BiTree thrt,BiTree t);//先序 void pre_threading(BiTree p); void preorder_traverse(BiTree thrt); BiTree inorder_threading(BiTree thrt,BiTree t);//中序 void in_threading(BiTree p); void inorder_traverse(BiTree thrt); BiTree postorder_threading(BiTree thrt,BiTree t);//后序 void post_threading(BiTree p); void postorder_traverse(BiTree thrt); int main() { printf("now create the bintree first,please input :\n"); bintree_creat(&T); welcome(T); return 0; } int bintree_creat(BiTree *q) { char ch; ch=getchar(); if(ch=='#') (*q)=NULL; else { (*q) = (BiTree )malloc(len); if((*q)) { (*q)->data = ch; (*q)->ltag = link; (*q)->rtag = link; bintree_creat(&(*q) -> lchild); bintree_creat(&(*q) -> rchild); } } return OK; } void welcome(BiTree t) { int i; printf("input 1 :preorder_threading the bintree .\n"); printf("input 2 :inorder_threading the bintree .\n"); printf("input 3 :postorder_threading the bintree .\n\n"); scanf("%d",&i); switch (i) { case 1 :thrt = preorder_threading(thrt,t); preorder_traverse(thrt); printf("\n\n"); break; case 2 :thrt = inorder_threading(thrt,t); inorder_traverse(thrt); printf("\n\n"); break; case 3 :thrt = postorder_threading(thrt,t); postorder_traverse(thrt); printf("\n\n"); break; default :printf("input error !"); exit(1); } } BiTree preorder_threading(BiTree thrt,BiTree t) { thrt = (BiTree )malloc(len); if(! thrt) exit(0); thrt -> rtag = thread; thrt -> rchild = thrt; thrt -> ltag = link; if(!t) thrt -> lchild = thrt; else { thrt -> lchild = t; pre = thrt; pre_threading(t); pre -> rtag = thread; pre -> rchild = thrt; thrt -> rchild = pre; } return thrt; } void pre_threading(BiTree p) { if(p) { if(! p->lchild) { p -> ltag = thread; p -> lchild = pre; } if(!p -> rchild) p -> rtag = thread; if(pre && pre->rtag == thread) pre -> rchild = p; pre = p; if(p->ltag == link) pre_threading(p -> lchild); if(p->rtag == link) pre_threading(p -> rchild); } } void preorder_traverse(BiTree thrt) { BiTree p = thrt -> lchild; printf("%c ",p->data); while(p->rchild != thrt) { if(p->ltag == link) p = p->lchild; else p = p->rchild; printf("%c ",p->data); } } BiTree inorder_threading(BiTree thrt,BiTree t) { thrt = (BiTree )malloc(len);//建立头指针 if(!thrt) exit(0); thrt->rtag = thread;//右指针回指 thrt->rchild = thrt; thrt->ltag = link; if(!t)//若二叉树空,左指针回指 thrt->lchild = thrt; else { thrt->lchild = t; pre = thrt; in_threading(t);//中序遍历进行中序线索化 pre->rtag = thread;//最后一个节点线索化 pre->rchild = thrt; thrt->rchild = pre; } return thrt; } void in_threading(BiTree p) { if(p) { in_threading(p -> lchild);//左子树线索化 if(! p->lchild)//前驱线索 { p->ltag = thread; p->lchild = pre; } if(! pre->rchild)//后继线索 { pre->rtag = thread; pre->rchild = p; } pre = p;//保持pre指向 p 的前驱 in_threading(p->rchild);//右子树线索化 } } void inorder_traverse(BiTree thrt) { BiTree p = thrt->lchild; while(p != thrt)//空树或遍历结束时,p==thrt { while(p->ltag == link) { p = p->lchild; } printf("%c ",p->data); if(p->rtag == thread && p->rchild != thrt) { p = p->rchild; printf("%c ",p->data); } p = p->rchild; } } BiTree postorder_threading(BiTree thrt,BiTree t) { thrt = (BiTree )malloc(len); if(! thrt) exit(0); thrt -> rtag = thread; thrt -> rchild = thrt; thrt -> ltag = link; if(!t) thrt -> lchild = thrt; else { thrt -> lchild = t; pre = thrt; post_threading(t); pre -> rtag = thread; pre -> rchild = thrt; thrt -> rchild = pre; } return thrt; } void post_threading(BiTree p) { if(p) { post_threading(p->lchild); //左子树线索化 post_threading(p->rchild); //右子树线索化 if(!p->lchild) { p->ltag=thread; p->lchild=pre; } if(!pre->rchild) { pre->rtag=thread; pre->rchild=p; } pre=p; } } void postorder_traverse(BiTree thrt) { BiTree p = thrt; while(p->ltag==link||p->rtag==link) //有左孩子先访问左孩子,没有左孩子先访问右孩子 { while(p->ltag==link) p=p->lchild; if(p->rtag==link) //访问左孩子为空的结点的右孩子 p=p->rchild; } printf("%c ",p->data); while(p!=T) //p不为根结点 { if(p->rtag==link) //若p是有兄弟的左孩子 { if(pre->rtag==thread||p==pre->rchild) //若p是双亲的右孩子或是独生左孩子,则后继为双亲 p=pre; else { p=pre->rchild; //后继为双亲的右子树上按照后序遍历访问的第一个结点。 while(p->ltag==link||p->rtag==link) { while(p->ltag==link) p=p->lchild; if(p->rtag==link) p=p->rchild; } } } else p=p->rchild; //p指向后继 printf("%c ",p->data); } }
(7)撰写匆忙,表述简陋,必有疏漏。欢迎朋友们批评指正。
2014/10/21
时间: 2024-11-05 11:34:53