线索二叉树

来源:互联网 发布:unity3d外包 编辑:程序博客网 时间:2024/06/06 00:05


//2013.7.4
//对线索二叉树有了更深入的理解。过去学习数据结构更注重代码实现。

//现在则更注重对算法思想的理解。因为只要有了思路,代码实现都没有问题(只要有一定程序调试能力)。

//至于线索二叉树以前只注意到线索二字。然而线索终究是给出一定指示即可,是不需要从头指向尾的。

//从头指向尾也没问题,但,二叉树只有左右两个指针。一个根节点如果有两个子节点的话。

//便没有多余的结点来供它来做线索来指向了!

//所以线索也只是对遍历的一种配合,中序线索二叉树,先让其走向最左端,然后按线索走向中间。

//然后再走向右端。



//-------------------二叉树的二叉树线索存储表示----------typedef enum PointerTag  { Link, Thread };            //Link == 0; 指针,Thread == 1;线索typedef struct BiThrNode {TElemType        data;struct BiThrNode  *lchild,  *rchild;                      //左右孩子指针PointerTag         LTag, RTag;                             //左右标志}BiThrNode,  *BiThrTree;Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType e)){      //T指向头结点,头结点的左链lchild指向根结点。 //中序遍历二叉树线索树T的非递归算法,对每个数据元素调用函数Visitp = T -> lchild;                                             //p指向根节点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 InOrderThreading (BinThrTree &Thrt, BiThrTree T) { //中序遍历二叉树T,并将其中序线索化,Thrt指向头结点if(!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode))))exit(OVERFLOW);Thrt -> LTag = Link;   Thrt -> Rtag = Thread;         //建立头结点Thrt -> rchild = Thrt;                                          //右指针回指if(!T)  Thrt -> lchild = Thrt;                                 //若二叉树空,则左指针回指else{Thrt -> lchild = T;   pre = Thrt;InThreading(T);                                             //中序遍历进行中序线索化pre -> rchild = Thrt;  pre -> RTag = Thread;      //最后一个结点线索化Thrt -> rchild = pre;                                     }return OK;}void InThreading(BinThree b) {if(p) {InThreading(p -> lchild);                               //左子树线索化     if(!p -> lchild) {p -> LTag = Thread; p -> lchild = pre; }//前驱线索if(!p -> rchild) {pre -> RTag = Thread; pre -> rchild = p;}  //后继线索化pre =p;                                                   //保持pre指向p的前驱InThreading(p -> rchild);                             //右子树线索化}}




//2013.2.23#include <stdio.h>#include<malloc.h>#define LEN sizeof(struct ThreadBinTree)#define NULL 0enum NodeFlag{SubTree,Thread};                                                                //枚举值SubTree和Thread分别为0,1struct ThreadBinTree{int data;                                                  //元素数据NodeFlag lflag;                                          //左标志NodeFlag rflag;                                          //右标志struct ThreadBinTree *left;                                 //左子树结点指针struct ThreadBinTree *right;                               //右子树结点指针};ThreadBinTree *Previous;void BinTreeThreading_LDR(ThreadBinTree *bt)                //二叉树按中序线索化{if(bt){BinTreeThreading_LDR(bt->left);                          //递归调用,将左子树线索化bt->lflag=(bt->left)?SubTree:Thread;                //设置左指针域的标志bt->rflag=(bt->right)?SubTree:Thread;                  //设置右指针域的标志if(Previous)                                            //若当前结点的前驱Previous存在{if(Previous->rflag==Thread)                 //若当前结点的前驱右标志为线索Previous->right=bt;                         //设Previous的右线索指向后继if(bt->lflag==Thread)                         //若当前结点的左标志为线索bt->left=Previous;                          //设当前结点的左线索指向中序前驱}Previous=bt;                                            //让Previous保存刚访问的结点BinTreeThreading_LDR(bt->right);                //递归调用将右子树线索化}}ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt)           //求指定结点的后继{ThreadBinTree *nextnode;if(!bt)return NULL;if(bt->rflag==Thread)                                       //若当前结点的右子树为空return bt->right;                                         //返回右线索所指的中序后继else{nextnode=bt->right;                                     //从当前1结点的右子树开始查找while(nextnode->lflag==SubTree)                  //循环处理所有左子树不为空的结点nextnode=nextnode->left;return nextnode;                                          //返回左下方的结点}}ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt)      //求指定结点的前驱{ThreadBinTree *prenode;if(!bt)return NULL;                                              if(bt->lflag==Thread)                                      //若当前解结点的左子树为空return bt->left;                                         //返回左线索所指的中序后继else{prenode=bt->left;                                      //从当前结点的左子树开始查找while(prenode->rflag==SubTree)                 //循环处理所有右子树不为空的结点prenode=prenode->left;                return prenode;                                          //返回左下方结点}}void ThreadBinTree_LDR(ThreadBinTree *bt){if(bt){while(bt->lflag==SubTree)                          //有左子树bt=bt->left;                                          //从根往下找最左下结点do{printf("%d",bt->data);                                   //处理结点bt=BinTreeNext_LDR(bt);                                  //找中序后继结点}while(bt);}}/*函数功能初始化一个二叉树,建立根节点。*/ThreadBinTree *InitRoot(){ThreadBinTree *node;      node=(struct ThreadBinTree*)malloc(LEN);printf("请输入根节点的值:");scanf("%d",&node->data);node->left=NULL;node->right=NULL;return node;}/*函数功能:进行查找操作。*/ThreadBinTree *BinTreeFind(ThreadBinTree *bt,int data)            //在二叉树中查找值为data的结点。{ThreadBinTree *p;if(bt==NULL)return NULL;else{if(bt->data==data)return bt;else{if(p=BinTreeFind(bt->left,data))return p;     else if(p=BinTreeFind(bt->right,data))     return p;     else     return NULL;      }}}/*添加数据到二叉树*/int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n){if(bt==NULL){printf("\n父结点不在,请先设置父结点。");return 0;}switch(n){case 1:if(bt->left){printf("左子树结点不为空。");return 0;}elsebt->left=node;break;case 2:if(bt->right){printf("右子树结点不为空。");return 0;}elsebt->right=node;break;default:printf("参数错误!\n");return 0; }return 1;}/*函数功能:添加结点到二叉树。*/void AddNode(ThreadBinTree *bt){int data;int select;ThreadBinTree *node,*parent;     node=(struct ThreadBinTree*)malloc(LEN);printf("\n输入二叉树结点数据");scanf("%d",&node->data);node->left=NULL;node->right=NULL;printf("\n输入父结点数据:");scanf("%d",&data);parent=BinTreeFind(bt,data);if(!parent){printf("\n未找到父结点。");}printf("\n1.添加到左子树\n2.添加到右子树\n");do{scanf("%d",&select);if(select==1||select==2)BinTreeAddNode(parent,node,select);}while(select!=1&&select!=2);}int main(){ThreadBinTree *root=NULL;int select;do{printf("\n1.设置二叉树根元素\n2.添加二叉树根节点\n3.生成中序线索二叉树\n4.遍历线索二叉树\n0.退出");scanf("%d",&select);switch(select){case 1:root=InitRoot();     break;case 2:AddNode(root);     break;case 3:BinTreeThreading_LDR(root);     printf("生成线索二叉树完毕");     break;case 4:printf("\n中序线索二叉树遍历的结果");     ThreadBinTree_LDR(root);      break;case 0:break;}}while(select!=0);return 0;}




原创粉丝点击