标签:
3.3 c
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define QUEUE_MAXSIZE 50 4 typedef char DATA; //定义元素类型 5 typedef enum 6 { 7 SubTree, 8 Thread 9 }NodeFlag; //枚举值SubTree(子树)和Thread(线索)分别为0,1 10 typedef struct ThreadTree //定义线索二叉树结点类型 11 { 12 DATA data; //元素数据 13 NodeFlag lflag; //左标志 14 NodeFlag rflag; //右标志 15 struct ThreadTree *left; //左子树结点指针 16 struct ThreadTree *right; //右子树结点指针 17 }ThreadBinTree; 18 19 ThreadBinTree *Previous=NULL; //前驱结点指针 20 21 ThreadBinTree *BinTreeInit(ThreadBinTree *node) //初始化二叉树根结点 22 { 23 if(node!=NULL) //若二叉树根结点不为空 24 return node; 25 else 26 return NULL; 27 } 28 int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) //添加数据到二叉树 29 //bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树 30 { 31 if(bt==NULL) 32 { 33 printf("父结点不存在,请先设置父结点!\n"); 34 return 0; 35 } 36 switch(n) 37 { 38 case 1: //添加到左结点 39 if(bt->left) //左子树不为空 40 { 41 printf("左子树结点不为空!\n"); 42 return 0; 43 }else 44 bt->left=node; 45 break; 46 case 2://添加到右结点 47 if( bt->right) //右子树不为空 48 { 49 printf("右子树结点不为空!\n"); 50 return 0; 51 }else 52 bt->right=node; 53 break; 54 default: 55 printf("参数错误!\n"); 56 return 0; 57 } 58 return 1; 59 } 60 ThreadBinTree *BinTreeLeft(ThreadBinTree *bt) //返回左子结点 61 { 62 if(bt) 63 return bt->left; 64 else 65 return NULL; 66 } 67 ThreadBinTree *BinTreeRight(ThreadBinTree *bt) //返回右子结点 68 { 69 if(bt) 70 return bt->right; 71 else 72 return NULL; 73 } 74 int BinTreeIsEmpty(ThreadBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0 75 { 76 if(bt) 77 return 0; 78 else 79 return 1; 80 } 81 int BinTreeDepth(ThreadBinTree *bt) //求二叉树深度 82 { 83 int dep1,dep2; 84 if(bt==NULL) 85 return 0; //对于空树,深度为0 86 else 87 { 88 dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用) 89 dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用) 90 if(dep1>dep2) 91 return dep1 + 1; 92 else 93 return dep2 + 1; 94 } 95 } 96 ThreadBinTree *BinTreeFind(ThreadBinTree *bt,DATA data) //在二叉树中查找值为data的结点 97 { 98 ThreadBinTree *p; 99 if(bt==NULL) 100 return NULL; 101 else 102 { 103 if(bt->data==data) 104 return bt; 105 else{ // 分别向左右子树递归查找 106 if(p=BinTreeFind(bt->left,data)) 107 return p; 108 else if(p=BinTreeFind(bt->right, data)) 109 return p; 110 else 111 return NULL; 112 } 113 } 114 } 115 void BinTreeClear(ThreadBinTree *bt) // 清空二叉树,使之变为一棵空树 116 { 117 if(bt) 118 { 119 BinTreeClear(bt->left); //清空左子树 120 BinTreeClear(bt->right);//清空右子树 121 free(bt);//释放当前结点所占内存 122 bt=NULL; 123 } 124 return; 125 } 126 void BinTree_DLR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //先序遍历 127 { 128 if(bt)//树不为空,则执行如下操作 129 { 130 oper(bt); //处理结点的数据 131 BinTree_DLR(bt->left,oper); 132 BinTree_DLR(bt->right,oper); 133 } 134 return; 135 } 136 void BinTree_LDR(ThreadBinTree *bt,void(*oper)(ThreadBinTree *p)) //中序遍历 137 { 138 if(bt)//树不为空,则执行如下操作 139 { 140 BinTree_LDR(bt->left,oper); //中序遍历左子树 141 oper(bt);//处理结点数据 142 BinTree_LDR(bt->right,oper); //中序遍历右子树/ 143 } 144 return; 145 } 146 void BinTree_LRD(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //后序遍历 147 { 148 if(bt) 149 { 150 BinTree_LRD(bt->left,oper); //后序遍历左子树 151 BinTree_LRD(bt->right,oper); //后序遍历右子树/ 152 oper(bt); //处理结点数据 153 } 154 return; 155 } 156 void BinTree_Level(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //按层遍历 157 { 158 ThreadBinTree *p; 159 ThreadBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈 160 int head=0,tail=0;//队首、队尾序号 161 if(bt)//若队首指针不为空 162 { 163 tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号 164 q[tail] = bt;//将二叉树根指针进队 165 } 166 while(head!=tail) //队列不为空,进行循环 167 { 168 head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号 169 p=q[head]; //获取队首元素 170 oper(p);//处理队首元素 171 if(p->left!=NULL) //若结点存在左子树,则左子树指针进队 172 { 173 tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 174 q[tail]=p->left;//将左子树指针进队 175 } 176 177 if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队 178 { 179 tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 180 q[tail]=p->right;//将右子树指针进队 181 } 182 } 183 return; 184 } 185 void BinTreeThreading_LDR(ThreadBinTree *bt) //将二叉树p中序线索化 186 { 187 if(bt) //p非空时,当前访问结点是*p 188 { 189 BinTreeThreading_LDR(bt->left); //递归调用,将左子树线索化 190 //以下直至右子树线索化之前相当于遍历算法中访问结点的操作 191 bt->lflag=(bt->left)?SubTree:Thread; //设置左指针域的标志 192 bt->rflag=(bt->right)?SubTree:Thread;//设置右指针域的标志 193 if(Previous) //若p的前趋Previous存在 194 { 195 if(Previous->rflag==Thread) //若*p的前驱右标志为线索 196 Previous->right=bt;//令*Previous的右线索指向后继 197 if(bt->lflag==Thread) //*p的左标志为线索 198 bt->left=Previous;//令*p的左线索指向中序前驱 199 } 200 Previous=bt;//让Previous保存刚访问的结点 201 BinTreeThreading_LDR(bt->right);//递归调用,将右子树线索化 202 } 203 } 204 ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt) //求指定结点的后继 205 { 206 ThreadBinTree *nextnode; 207 if(!bt) return NULL; //若当前结点为空,则返回空 208 if(bt->rflag==Thread) //若当前结点的右子树为空 209 return bt->right; //返回右线索所指的中序后继 210 else{ 211 nextnode=bt->right; //从当前结点的右子树开始查找 212 while(nextnode->lflag==SubTree) //循环处理所有左子树不为空的结点 213 nextnode=nextnode->left; 214 return nextnode; //返回左下方的结点 215 } 216 } 217 ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt) //求指定结点的前驱 218 { 219 ThreadBinTree *prenode; 220 if(!bt) return NULL; //若当前结点为空,则返回空 221 if(bt->lflag==Thread) //若当前结点的左子树为空 222 return bt->left; //返回左线索所指的中序后继 223 else{ 224 prenode=bt->left; //从当前结点的左子树开始查找 225 while(prenode->rflag==SubTree) //循环处理所有右子树不为空的结点 226 prenode=prenode->left; 227 return prenode; //返回左下方的结点 228 } 229 } 230 231 void ThreadBinTree_LDR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //遍历中序线索二叉树 232 { 233 if(bt) //二叉树不为空 234 { 235 while(bt->lflag==SubTree)//有左子树 236 bt=bt->left; //从根往下找最左下结点,即中序序列的开始结点 237 do{ 238 oper(bt); //处理结点 239 bt=BinTreeNext_LDR(bt);//找中序后继结点 240 }while(bt); 241 } 242 } 243 244 void main()
3-4 ThreadBinTreeTest.c
1 #include <stdio.h> 2 #include "3-3 ThreadBinTree.c" 3 void oper(ThreadBinTree *p) //操作二叉树结点数据 4 { 5 printf("%c ",p->data); //输出数据 6 return; 7 } 8 ThreadBinTree *InitRoot() //初始化二叉树的根 9 { 10 ThreadBinTree *node; 11 if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存 12 { 13 printf("\n输入根结点数据:"); 14 scanf("%s",&node->data); 15 node->left=NULL; 16 node->right=NULL; 17 return BinTreeInit(node); 18 } 19 return NULL; 20 } 21 void AddNode(ThreadBinTree *bt) 22 { 23 ThreadBinTree *node,*parent; 24 DATA data; 25 char select; 26 if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存 27 { 28 printf("\n输入二叉树结点数据:"); 29 fflush(stdin);//清空输入缓冲区 30 scanf("%s",&node->data); 31 node->left=NULL; //设置左右子树为空 32 node->right=NULL; 33 34 35 printf("输入父结点数据:"); 36 fflush(stdin);//清空输入缓冲区 37 scanf("%s",&data); 38 parent=BinTreeFind(bt,data);//查找指定数据的结点 39 if(!parent)//若未找到指定数据的结点 40 { 41 printf("未找到父结点!\n"); 42 free(node); //释放创建的结点内存 43 return; 44 } 45 printf("1.添加到左子树\n2.添加到右子树\n"); 46 do{ 47 select=getch(); 48 select-=‘0‘; 49 if(select==1 || select==2) 50 BinTreeAddNode(parent,node,select); //添加结点到二叉树 51 }while(select!=1 && select!=2); 52 } 53 return ; 54 } 55 int main() 56 { 57 ThreadBinTree *root=NULL; //root为指向二叉树根结点的指针 58 char select; 59 void (*oper1)(); //指向函数的指针 60 oper1=oper; //指向具体操作的函数 61 do{ 62 printf("\n1.设置二叉树根元素 2.添加二叉树结点\n"); 63 printf("3.生成中序线索二叉树 4.遍历线索二叉树\n"); 64 printf("0.退出\n"); 65 select=getch(); 66 switch(select){ 67 case ‘1‘: //设置根元素 68 root=InitRoot(); 69 break; 70 case ‘2‘: //添加结点 71 AddNode(root); 72 break; 73 case ‘3‘://生成中序线索二叉树 74 BinTreeThreading_LDR(root); 75 printf("\n生成中序线索二叉树完毕!\n"); 76 break; 77 case ‘4‘://遍历中序线索二叉树 78 printf("\n中序线索二叉树遍历的结果:"); 79 ThreadBinTree_LDR(root,oper1); 80 printf("\n"); 81 break; 82 case ‘0‘: 83 break; 84 } 85 }while(select!=‘0‘); 86 BinTreeClear(root);//清空二叉树 87 root=NULL; 88 getch(); 89 return 0; 90 }
#include <stdio.h> #include <stdlib.h> #define QUEUE_MAXSIZE 50typedefchar DATA; //定义元素类型 typedefenum { SubTree, Thread }NodeFlag; //枚举值SubTree(子树)和Thread(线索)分别为0,1typedefstruct ThreadTree //定义线索二叉树结点类型 { DATA data; //元素数据 NodeFlag lflag; //左标志 NodeFlag rflag; //右标志 struct ThreadTree *left; //左子树结点指针struct ThreadTree *right; //右子树结点指针 }ThreadBinTree; ThreadBinTree *Previous=NULL; //前驱结点指针 ThreadBinTree *BinTreeInit(ThreadBinTree *node) //初始化二叉树根结点 { if(node!=NULL) //若二叉树根结点不为空 return node; elsereturn NULL; } int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) //添加数据到二叉树 //bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树 { if(bt==NULL) { printf("父结点不存在,请先设置父结点!\n"); return0; } switch(n) { case1: //添加到左结点 if(bt->left) //左子树不为空 { printf("左子树结点不为空!\n"); return0; }else bt->left=node; break; case2://添加到右结点if( bt->right) //右子树不为空 { printf("右子树结点不为空!\n"); return0; }else bt->right=node; break; default: printf("参数错误!\n"); return0; } return1; } ThreadBinTree *BinTreeLeft(ThreadBinTree *bt) //返回左子结点 { if(bt) return bt->left; elsereturn NULL; } ThreadBinTree *BinTreeRight(ThreadBinTree *bt) //返回右子结点 { if(bt) return bt->right; elsereturn NULL; } int BinTreeIsEmpty(ThreadBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0 { if(bt) return0; elsereturn1; } int BinTreeDepth(ThreadBinTree *bt) //求二叉树深度 { int dep1,dep2; if(bt==NULL) return0; //对于空树,深度为0else { dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用) dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)if(dep1>dep2) return dep1 + 1; elsereturn dep2 + 1; } } ThreadBinTree *BinTreeFind(ThreadBinTree *bt,DATA 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; elseif(p=BinTreeFind(bt->right, data)) return p; elsereturn NULL; } } } void BinTreeClear(ThreadBinTree *bt) // 清空二叉树,使之变为一棵空树 { if(bt) { BinTreeClear(bt->left); //清空左子树 BinTreeClear(bt->right);//清空右子树 free(bt);//释放当前结点所占内存 bt=NULL; } return; } void BinTree_DLR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //先序遍历 { if(bt)//树不为空,则执行如下操作 { oper(bt); //处理结点的数据 BinTree_DLR(bt->left,oper); BinTree_DLR(bt->right,oper); } return; } void BinTree_LDR(ThreadBinTree *bt,void(*oper)(ThreadBinTree *p)) //中序遍历 { if(bt)//树不为空,则执行如下操作 { BinTree_LDR(bt->left,oper); //中序遍历左子树 oper(bt);//处理结点数据 BinTree_LDR(bt->right,oper); //中序遍历右子树/ } return; } void BinTree_LRD(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //后序遍历 { if(bt) { BinTree_LRD(bt->left,oper); //后序遍历左子树 BinTree_LRD(bt->right,oper); //后序遍历右子树/ oper(bt); //处理结点数据 } return; } void BinTree_Level(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //按层遍历 { ThreadBinTree *p; ThreadBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈 int head=0,tail=0;//队首、队尾序号 if(bt)//若队首指针不为空 { tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号 q[tail] = bt;//将二叉树根指针进队 } while(head!=tail) //队列不为空,进行循环 { head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号 p=q[head]; //获取队首元素 oper(p);//处理队首元素 if(p->left!=NULL) //若结点存在左子树,则左子树指针进队 { tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 q[tail]=p->left;//将左子树指针进队 } if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队 { tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 q[tail]=p->right;//将右子树指针进队 } } return; } void BinTreeThreading_LDR(ThreadBinTree *bt) //将二叉树p中序线索化 { if(bt) //p非空时,当前访问结点是*p { BinTreeThreading_LDR(bt->left); //递归调用,将左子树线索化//以下直至右子树线索化之前相当于遍历算法中访问结点的操作 bt->lflag=(bt->left)?SubTree:Thread; //设置左指针域的标志 bt->rflag=(bt->right)?SubTree:Thread;//设置右指针域的标志if(Previous) //若p的前趋Previous存在 { if(Previous->rflag==Thread) //若*p的前驱右标志为线索 Previous->right=bt;//令*Previous的右线索指向后继if(bt->lflag==Thread) //*p的左标志为线索 bt->left=Previous;//令*p的左线索指向中序前驱 } 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; //从当前结点的右子树开始查找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,void (*oper)(ThreadBinTree *p)) //遍历中序线索二叉树 { if(bt) //二叉树不为空 { while(bt->lflag==SubTree)//有左子树 bt=bt->left; //从根往下找最左下结点,即中序序列的开始结点do{ oper(bt); //处理结点 bt=BinTreeNext_LDR(bt);//找中序后继结点 }while(bt); } } void main()
标签:
原文地址:http://www.cnblogs.com/wozixiaoyao/p/5683127.html