家谱图-二叉树
因为树有多种表示方式,也可以不用二叉树来表示,但是那样有局限性, 就比如一个节点有几个孩子,这个数目都是不确定的,如果用二叉树来表示,那样就比较清楚的显示出家谱中的人员组成,但是不能用孩子表示法,因为那样最多只能表示两个孩子,但是可以转化一下表示方法,用孩子兄弟表示方法来表示,那样,就可以有无限多个(理论上)孩子,就是一个节点有两个指针,一个指向第一个孩子,一个指向它的右兄弟,所以,这种二叉树可以表示好多方式,其实和那种二叉树一样,只是解释不一样了而已,在计算机中更是差不多,因为计算机没有这些逻辑,这些都是我们为了方便而想象出来的,家谱图主要实现的功能有增加节点,查询一个节点的子节点,删除一个节点(同时删除)它的子树。
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef char TElemType; 5 6 //孩子兄弟表示法 7 typedef struct Tree{ 8 TElemType data; 9 struct Tree *firstchild, *rightbro; 10 }CSNode, *PCSTree; 11 12 PCSTree ptr; 13 char data; 14 15 void createTree(PCSTree *T)//创建二叉树 16 { 17 TElemType data; 18 scanf("%c", &data); 19 getchar(); 20 if(data == ' ') 21 *T = NULL; 22 else 23 { 24 *T = (PCSTree)malloc(sizeof(CSNode)); 25 (*T) -> data = data; 26 printf("Please input %c's first child\n", data); 27 createTree(&(*T) -> firstchild); 28 printf("Please input %c's right brother\n", data); 29 createTree(&(*T) -> rightbro); 30 } 31 } 32 33 void preOrderTraverse(PCSTree T)//前续遍历 34 { 35 if(T == NULL) 36 return ; 37 printf("%c ", T -> data); 38 preOrderTraverse(T -> firstchild); 39 preOrderTraverse(T -> rightbro); 40 } 41 42 void findChild(PCSTree T, char data)//查找某个节点的孩子 43 { 44 if (T == NULL) 45 return ; 46 PCSTree p; 47 p = T->firstchild; 48 if (T->data == data) 49 { 50 if(p == NULL) 51 { 52 printf("No member!\n"); 53 return; 54 } 55 while (p->rightbro != NULL)//打印出来他所有的孩子 56 { 57 printf("%c ", p->data); 58 p = p->rightbro; 59 } 60 printf("%c\n", p->data); 61 return ; 62 } 63 else 64 { 65 findChild(T->firstchild, data);//如果找不到的话,继续找他的子节点 66 findChild(T->rightbro, data); 67 } 68 } 69 70 int addMember(PCSTree *T)//添加新成员 71 { 72 if(*T == NULL)//用于递归时判断退出条件 73 return 0; 74 PCSTree pt; 75 if ((*T)->data == data)//找到父节点 76 { 77 if ((*T)->firstchild != NULL) 78 { 79 pt = (*T)->firstchild; 80 while(pt->rightbro != NULL)//找到最右边的一个添加新节点 81 pt = pt->rightbro; 82 pt->rightbro = ptr; 83 return 1;//添加成功, 返回1 84 } 85 (*T)->firstchild = ptr; 86 return 1; 87 } 88 89 if (addMember(&(*T)->firstchild) == 1)//递归再找匹配的父节点 90 return 1; 91 if (addMember(&(*T)->rightbro) == 1) 92 return 1; 93 return 0; 94 } 95 96 void findAndFree(PCSTree *T)//找到传过来的某个节点并且将它释放掉,并且释放掉它所有的子节点 97 { 98 if(*T == NULL) 99 return; 100 PCSTree p1, p2; 101 p1 = (*T)->firstchild; 102 p2 = (*T)->rightbro; 103 findAndFree(&p1); 104 findAndFree(&p2); 105 free(*T); 106 } 107 108 int deleteMember(PCSTree *T)//删除节点函数(删除其子树) 109 { 110 PCSTree pt; 111 if(*T == NULL) 112 return 0; 113 //类似链表中的删除,要删除当前元素,先要找到它的前一个 114 if((*T)->firstchild == NULL && (*T)->rightbro == NULL) 115 { 116 if ((*T)->data == data) 117 { 118 free(*T); 119 return 1; 120 } 121 return 0; 122 } 123 //如果是它的子节点 124 if((*T)->firstchild != NULL && (*T)->firstchild->data == data) 125 { 126 pt = (*T)->firstchild; 127 if (pt->rightbro != NULL) 128 { 129 (*T)->firstchild = pt->rightbro; 130 } 131 else 132 (*T)->firstchild = NULL; 133 if(pt->firstchild != NULL) 134 findAndFree(&(pt->firstchild)); 135 free(pt); 136 return 1; 137 } 138 //如果是它的右兄弟节点 139 else if ((*T)->rightbro != NULL && (*T)->rightbro->data == data) 140 { 141 pt = (*T)->rightbro; 142 if (pt->rightbro != NULL) 143 { 144 (*T)->rightbro = pt->rightbro; 145 146 } 147 else 148 (*T)->rightbro = NULL; 149 if(pt->firstchild != NULL) 150 findAndFree(&(pt->firstchild)); 151 free(pt); 152 return 1; 153 } 154 //如果都不是,继续递归 找 155 if(deleteMember(&(*T)->firstchild)) 156 return 1; 157 if(deleteMember(&(*T)->rightbro)) 158 return 1; 159 return 0; 160 } 161 162 163 int main() 164 { 165 // freopen("in.txt", "r", stdin); 166 PCSTree T; 167 printf("Input root Node:\n"); 168 createTree(&T);//create binary tree 169 printf("The previous traverse are:\n"); 170 preOrderTraverse(T);//previous traverse the tree 171 printf("\n"); 172 char newdata; 173 int choice; 174 do{ 175 printf("1. find some node's kids 2. add member\n"); 176 printf("3. delete some node 4. previous traverse the tree\n"); 177 printf("0. exit\n"); 178 scanf("%d", &choice); 179 switch(choice) 180 { 181 case 1: 182 printf("\nPlease input you want find child name:\n"); 183 getchar(); 184 scanf("%c", &data); 185 findChild(T, data); 186 printf("\n"); 187 break; 188 case 2: 189 if(T == NULL) 190 { 191 printf("Input root node:\n"); 192 getchar(); 193 createTree(&T); 194 } 195 else 196 { 197 printf("Please input you want add data\n"); 198 printf("Format: father child\n"); 199 ptr = (PCSTree)malloc(sizeof(CSNode)); 200 ptr->firstchild = ptr->rightbro = NULL; 201 getchar(); 202 scanf("%c %c", &data, &newdata); 203 ptr->data = newdata; 204 addMember(&T); 205 preOrderTraverse(T); 206 printf("\n"); 207 } 208 break; 209 case 3: 210 if(T == NULL) 211 { 212 printf("No member\n"); 213 break; 214 } 215 printf("Please input you want delete node\n"); 216 getchar(); 217 scanf("%c", &data); 218 if(data == T->data) 219 { 220 findAndFree(&T); 221 T = NULL; 222 } 223 else 224 deleteMember(&T); 225 break; 226 case 4: 227 if(T != NULL) 228 preOrderTraverse(T); 229 else 230 printf("No member"); 231 printf("\n"); 232 break; 233 default: 234 break; 235 } 236 }while(choice != 0); 237 return 0; 238 }