坑坑爹爹连改带抄的把代码坑了出来
View Code
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <queue> 4 #include <Windows.h> 5 const int MAX = 10; 6 typedef int KeyType ; 7 typedef struct Node{ 8 int keynum;//关键字数目 9 KeyType key[MAX];//关键字 由1开始 10 Node *parent; 11 Node *child[MAX]; 12 }BTree; 13 14 typedef struct Node2{ 15 BTree *result;//找到的节点 16 int flag;//判断查找是否成功 17 int num;//找到的位置 18 }Result; 19 20 struct QueueNode{ 21 BTree *p; 22 int step; 23 }; 24 int m;//阶数 25 int max;//最大关键字数 max = m - 1 26 int min;//最小关键字数 min = (m - 1)/2 27 28 /*查找函数: 1.搜索结点Q,找k的位置或者k应该插入的位置*/ 29 int Search(BTree *Q,KeyType k) 30 { 31 int i; 32 for(i=0;i<Q->keynum;i++) 33 { 34 if(Q->key[i+1] > k) 35 { 36 break; 37 } 38 } 39 return i; 40 } 41 /*查找函数: 2.搜索树T,查找成功则跳出循环,查找不成功则向下一层查找,直到最底层*/ 42 Result SearchBTree(BTree *T,KeyType k) 43 { 44 int i=0; 45 BTree *p = T; 46 BTree *q = NULL; 47 Result Re; 48 int found = 0; 49 50 while(p!=NULL) 51 { 52 i = Search(p,k); 53 if(i>0 && p->key[i] == k) 54 { 55 found = 1; 56 break; 57 } 58 else 59 { 60 q = p;//保存父节点 61 p = p->child[i]; 62 } 63 } 64 65 Re.num = i; 66 if(found == 1)//查找成功返回当前位置 67 { 68 Re.flag = 1; 69 Re.result = p; 70 } 71 else//查找失败返回父节点位置 72 { 73 Re.flag = 0; 74 Re.result = q; 75 } 76 return Re; 77 } 78 79 80 /*插入函数: 3.在结点Q中的第 i+1 位置插入关键字为k 和 子树mid*/ 81 void Insert(BTree *Q,KeyType k,int i,BTree *mid) 82 { 83 int j; 84 for(j=Q->keynum;j>i;j--) 85 { 86 Q->key[j+1] = Q->key[j]; 87 Q->child[j+1] = Q->child[j]; 88 } 89 Q->key[i+1] = k; 90 Q->child[i+1] = mid; 91 if(mid!=NULL) 92 { 93 mid->parent = Q; 94 } 95 Q->keynum++; 96 } 97 /*插入函数: 4.分裂结点 98 左子树为原来的结点,不需要做多余的操作. 99 右子树为新申请的结点,没有与父结点相连. 100 且中间的数值还没有插入到父结点中,所以要结合插入操作. 101 */ 102 void Split(BTree *Q,BTree **mid) 103 { 104 int sum = (m+1)/2; 105 (*mid) = (BTree*)malloc(sizeof(BTree)); 106 107 (*mid)->keynum = Q->keynum - sum;//新的结点的关键字数 108 Q->keynum = sum-1;//旧结点关键字数 109 (*mid)->parent = Q->parent ;//有相同的父结点 110 111 int i; 112 (*mid)->child[0] = Q->child[sum];//新结点第0个子树做特殊处理 113 for(i=sum+1;i<=m;i++) 114 { 115 (*mid)->child[i-sum] = Q->child[i]; 116 (*mid)->key[i-sum] = Q->key[i]; 117 } 118 for(i=0;i<(*mid)->keynum;i++)//修改父结点 119 { 120 if((*mid)->child[i]!=NULL) 121 { 122 (*mid)->child[i]->parent = (*mid); 123 } 124 } 125 } 126 /*插入函数: 5.建立新的根结点*/ 127 void SetRoot(BTree **T,BTree *Q,KeyType k,BTree *mid) 128 { 129 (*T) = (BTree*) malloc (sizeof(BTree)); 130 (*T)->child[0] = Q;//左子树 131 (*T)->child[1] = mid;//右子树 132 (*T)->key[1] = k;//关键字 133 (*T)->keynum = 1;//关键字数目 134 (*T)->parent = NULL;//父结点 135 if(Q!=NULL) 136 { 137 Q->parent = (*T); 138 } 139 if(mid!=NULL) 140 { 141 mid->parent = (*T); 142 } 143 } 144 /*插入函数: 6.在树T中插入k,若插入后实得节点过大则要分裂结点,调整B树的结构*/ 145 void InsertBTree(BTree **T,KeyType k,int i,BTree *result) 146 { 147 if(result == NULL)//如果result为NULL 则为空树 148 { 149 SetRoot(T,NULL,k,NULL); 150 } 151 else 152 { 153 BTree *mid = NULL; 154 int NewRoot = 0; 155 while(NewRoot == 0)//一直循环直到发现未满或者发现需要新的根节点为止 156 { 157 Insert(result,k,i,mid); 158 if(result->keynum <= max)//未满 则结束 159 { 160 break; 161 } 162 else//已满 分裂结点 163 { 164 Split(result,&mid); 165 int sum = (m+1)/2; 166 k = result->key[sum]; 167 if(result->parent != NULL) 168 { 169 result = result->parent; 170 i = Search(result,k); 171 } 172 else 173 { 174 NewRoot = 1; 175 SetRoot(T,result,k,mid); 176 } 177 } 178 } 179 } 180 } 181 182 /*删除函数:7.在结点Q中删除关键字和孩子指针*/ 183 void DeleteKey(BTree *Q,int num) 184 { 185 int i; 186 for(i=num+1;i <= Q->keynum ; i++) 187 { 188 Q->key[i-1] = Q->key[i]; 189 Q->child[i-1] = Q->child[i]; 190 } 191 Q->keynum--; 192 } 193 194 /*删除函数:8.查找被删除结点的替代结点并把替代结点替代白删除结点——查找该节点右子树的最小值*/ 195 void Replace(BTree *Q,int num) 196 { 197 BTree *mid = Q->child[num]; 198 while(mid->child[0]!=NULL) 199 { 200 mid = mid->child[0]; 201 } 202 Q->key[num] = mid->key[1]; //改变关键字 203 } 204 205 /*删除函数:9.把一个关键字移动的右兄弟中*/ 206 void MoveRight(BTree *Q,int num)//传入的Q为不符合的结点的父结点 207 { 208 int i; 209 BTree *mid = Q->child[num]; 210 for(i=mid->keynum;i>0;i--) 211 { 212 mid->key[i+1] = mid->key[i]; 213 mid->child[i+1] = mid->child[i]; 214 } 215 mid->child[1] = mid->child[0];//把关键字从父结点移动到右子节点 216 mid->key[1] = Q->key[num]; 217 mid->keynum++; 218 219 mid = Q->child[num-1];//把关键字从左子节点移到双亲结点 220 Q->key[num] = mid->key[mid->keynum]; 221 Q->child[num]->child[0] = mid->child[mid->keynum]; 222 mid->keynum--; 223 } 224 225 /*删除函数:10.把一个关键字移动的左兄弟中*/ 226 void MoveLeft(BTree *Q,int num) 227 { 228 int i; 229 BTree *mid = Q->child[num-1]; 230 mid->keynum++;//把关键字从父结点移动到左子节点 231 mid->key[mid->keynum] = Q->key[num]; 232 mid->child[mid->keynum] = Q->child[num]->child[0]; 233 234 mid = Q->child[num];//把关键字从右子节点移到双亲结点 235 Q->key[num] = mid->key[1]; 236 237 mid->child[0] = mid->child[1]; 238 for(i=1;i<mid->keynum;i++) 239 { 240 mid->key[i] = mid->key[i+1]; 241 mid->child[i] = mid->child[i+1]; 242 } 243 mid->keynum--; 244 } 245 246 /*删除函数:11.合并父结点中的一个关键字和左右子节点*/ 247 void Combine(BTree *Q,int num) 248 { 249 int i; 250 BTree *left = Q->child[num-1]; 251 BTree *right = Q->child[num];//指向右子节点,他将被删除. 252 left->keynum++; 253 left->key[left->keynum] = Q->key[num]; 254 left->child[left->keynum] = right->child[0]; 255 for(i=1;i<=right->keynum;i++) 256 { 257 left->keynum++; 258 left->key[left->keynum] = right->key[i]; 259 left->child[left->keynum] = right->child[i]; 260 } 261 262 for(i=num ; i<Q->keynum ; i++) 263 { 264 Q->key[i] = Q->key[i+1]; 265 Q->child[i] = Q->child[i+1]; 266 } 267 Q->keynum--; 268 free(right); 269 } 270 271 /*删除函数:12.判断B树是否需要调整和要调整的结点所在的位置*/ 272 void Judge(BTree *Q,int num) 273 { 274 if(num == 0)//最左边 275 { 276 if(Q->child[1]->keynum > min) 277 { 278 MoveLeft(Q,1); 279 } 280 else 281 { 282 Combine(Q,1); 283 } 284 } 285 else 286 { 287 if(num == Q->keynum)//最右边 288 { 289 if(Q->child[num-1]->keynum > min) 290 { 291 MoveRight(Q,num); 292 } 293 else 294 { 295 Combine(Q,num); 296 } 297 } 298 else 299 { 300 if(Q->child[num]->keynum > min) 301 { 302 MoveLeft(Q,num); 303 } 304 else 305 { 306 if(Q->child[num-1]->keynum > min) 307 { 308 MoveRight(Q,num); 309 } 310 else 311 { 312 Combine(Q,num); 313 } 314 } 315 } 316 } 317 } 318 319 /*删除函数:13.搜索要删除的函数在不在B树中,查找成功返回1,不成功返回0,且调整num的位置*/ 320 int SearchNode(BTree *Q,KeyType k,int *num) 321 { 322 int i; 323 for(i=1;i <= Q->keynum ;i++) 324 { 325 if(Q->key[i] == k) 326 { 327 *num = i; 328 return 1; 329 } 330 else 331 { 332 if(Q->key[i] > k) 333 { 334 *num = i-1; 335 return 0; 336 } 337 } 338 } 339 *num = i-1; 340 return 0; 341 } 342 343 /*删除函数:14.删除关键字以及调整B树结构*/ 344 int DeleteNode(BTree *Q,KeyType k) 345 { 346 int num; 347 int found; 348 if(Q==NULL) 349 { 350 return 0; 351 } 352 else 353 { 354 found = SearchNode(Q,k,&num); 355 if(found == 1) 356 { 357 if(Q->child[num] != NULL)//判断是否为叶子结点 358 { 359 Replace(Q,num);//寻找Q的右子树中的最小值代替他,完后后Q->key[num]变为代替的值 360 DeleteNode(Q->child[num],Q->key[num]); 361 } 362 else 363 { 364 DeleteKey(Q,num); 365 } 366 } 367 else 368 { 369 found = DeleteNode(Q->child[num],k); 370 } 371 372 if(Q->child[num] != NULL) 373 { 374 if(Q->child[num]->keynum < min) 375 { 376 Judge(Q,num); 377 } 378 } 379 return found; 380 } 381 } 382 383 /*删除函数:15.在B树中删除关键字,由于删除时只在右子树删除,所以若右子树没有其他元素则将他删除*/ 384 void DeleteBTree(BTree **T,KeyType k) 385 { 386 BTree *mid; 387 if(DeleteNode(*T,k) == 0) 388 { 389 printf("错误!!关键字不在B树中\n"); 390 } 391 else 392 { 393 if((*T)->keynum == 0) 394 { 395 mid = (*T); 396 (*T) = (*T)->child[0]; 397 free(mid); 398 } 399 } 400 } 401 402 /*输出函数:16.*/ 403 void Print(BTree *T) 404 { 405 std::queue <QueueNode> q; 406 if(T != NULL) 407 { 408 QueueNode mid; 409 mid.p = T; 410 mid.step = 1; 411 q.push(mid); 412 int step = 1; 413 while(!q.empty()) 414 { 415 int i; 416 mid = q.front(); 417 q.pop (); 418 if(mid.step != step) 419 { 420 printf("\n"); 421 step++; 422 } 423 printf("["); 424 for(i=1; i<=mid.p->keynum ; i++) 425 { 426 printf(" %d",mid.p->key[i]); 427 } 428 printf(" ] "); 429 430 for(i=0 ; i<=mid.p->keynum; i++) 431 { 432 QueueNode put; 433 put.p = mid.p->child[i]; 434 put.step = mid.step + 1; 435 if(put.p != NULL) 436 { 437 q.push(put); 438 } 439 } 440 } 441 } 442 } 443 444 445 int main() 446 { 447 //KeyType num[1100] = {4,9,0,1,8,6,3,5,2,7}; 448 KeyType num; 449 m=3; 450 max = m-1; 451 min = (m-1)/2; 452 int i; 453 BTree *T = NULL; 454 while(1) 455 { 456 printf("请输入要创建B树阶数:"); 457 scanf("%d",&m); 458 if(m>2) 459 { 460 break; 461 } 462 else 463 { 464 printf("错误!!B树阶数应该大于2\n"); 465 } 466 } 467 printf("\n"); 468 printf("创建一棵%d阶B树:\n\n",m); 469 while(1) 470 { 471 printf("请选择需要的操作:\n"); 472 printf("插入操作--1 删除操作--2 退出--0\n"); 473 int n; 474 scanf("%d",&n); 475 switch(n) 476 { 477 case 1: 478 system("CLS"); 479 Result s; 480 printf("请输入要插入的数字: "); 481 scanf("%d",&num); 482 printf("将%d插入B树:\n",num); 483 s = SearchBTree(T,num); 484 if(s.flag == 0) 485 { 486 InsertBTree(&T,num,s.num,s.result); 487 Print(T); 488 printf("\n\n"); 489 } 490 else 491 { 492 printf("错误!! 插入的数%d在已在B树中\n\n",num); 493 } 494 break; 495 case 2: 496 system("CLS"); 497 printf("删除操作:\n"); 498 printf("请输入要删除的数字: "); 499 scanf("%d",&num); 500 printf("\n"); 501 printf("删除%d:\n",num); 502 DeleteBTree(&T,num); 503 Print(T); 504 printf("\n\n"); 505 break; 506 case 0: 507 return 0; 508 default: 509 printf("输入错误\n"); 510 } 511 } 512 return 0; 513 }