二叉树的一些基本操作
1 #ifndef BITREE_H_INCLUDED 2 #define BITREE_H_INCLUDED 3 4 /************************************************ 5 *文件名: BiTree.h 6 *创建人: 水龙头 7 *日 期: 2019.7.22 8 *描 述: 二叉树的基本操作 9 ***********************************************/ 10 #define OK 1 11 #define ERROR -1 12 #define TRUE 1 13 #define FALSE 0 14 #define OVERFLOW -2 15 #define INFEASIBLE -1 16 typedef char TElemType; 17 typedef int Status; 18 //二叉树节点类型 19 typedef struct BiTNode 20 { 21 TElemType data; 22 int flag; //标志域,为了方便后序遍历的进行 23 struct BiTNode *lchild, *rchild; 24 25 }BiTNode, *BiTree; 26 //构造空二叉树 27 Status InitBiTree(BiTree&); 28 //创建一棵二叉树 29 Status CreateBiTree(BiTree&); 30 //先序遍历 31 Status PreOrderTraverse(const BiTree&, Status (*visit)(const BiTree&)); 32 //中序遍历 33 Status InOrderTraverse(const BiTree&, Status (*visit)(const BiTree&)); 34 //后序遍历 35 Status PostOrderTraverse(const BiTree&, Status (*visit)(const BiTree&)); 36 //层次遍历 37 Status LevelOrderTraverse(const BiTree&, Status (*visit)(const BiTree&)); 38 //销毁一颗二叉树 39 Status DestroyBiTree(BiTree&); 40 //清空一棵二叉树 41 Status ClearBiTree(BiTree&); 42 //判断一颗二叉树是否为空 43 Status BiTreeEmpty(const BiTree&); 44 //求二叉树的深度 45 Status BiTreeDepth(const BiTree&); 46 //插入一个节点 47 Status InsertChild(BiTree&); 48 //删除一个节点 49 Status DeleteChild(BiTree&); 50 //查找节点所在处 51 BiTree Location(const BiTree&, TElemType, Status (*compare)(BiTree, TElemType)); 52 //访问节点 53 Status Visit(const BiTree&); 54 //比较两关键字是否相等 55 Status Compare(BiTree, TElemType); 56 57 #endif // BITREE_H_INCLUDED 58 59 60 61 62 /************************************************ 63 *文件名: BiTree.cpp 64 *创建人: 水龙头 65 *日 期: 2019.7.22 66 *描 述: 二叉树的基本操作 67 ***********************************************/ 68 #include <iostream> 69 #include "BiTree.h" 70 #include "Stack.h" 71 #include "Queue.h" 72 //注意将各个头文件保持一致 73 using namespace std; 74 //构造空二叉树 75 Status InitBiTree(BiTree& T) 76 { 77 T = NULL; 78 return OK; 79 } 80 //创建一棵二叉树(先序递归创建) 81 Status CreateBiTree(BiTree& T) 82 { 83 //节点数据 84 TElemType ch; 85 cin >> ch; 86 if(ch == '@') 87 { 88 T = NULL; 89 return OK; 90 } 91 else 92 { 93 T = new BiTNode; 94 if(T) 95 { 96 T->data = ch; 97 CreateBiTree(T->lchild); 98 CreateBiTree(T->rchild); 99 return OK; 100 } 101 else 102 { 103 //节点创建失败,导致直接退出程序 104 exit(-1); 105 } 106 } 107 } 108 //先序遍历 109 Status PreOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&)) 110 { 111 //先序遍历的总体思路: 112 //如果左儿子存在,则将其压入栈中;如果左儿子不存在,则将栈顶元素弹出,并令指针指向其右儿子。 113 //在节点压入栈中之前就要将其访问掉。 114 BiTree ptr = T, p = NULL; 115 if(ptr) 116 { 117 //格式需要 118 cout << "先序遍历的结果为: "; 119 if(visit(ptr)) 120 { 121 //因为需要将指针压入栈中,所以需要使栈中的元素类型与指针类型保持一致 122 LinkList top = NULL; 123 Init_Stack(top); 124 Push(top, ptr); 125 ptr = ptr->lchild; 126 while(ptr || !StackEmpty(top)) 127 { 128 //如果左儿子存在 129 if(ptr) 130 { 131 if(visit(ptr)) 132 { 133 Push(top, ptr); 134 ptr = ptr->lchild; 135 } 136 //访问失败 137 else 138 return ERROR; 139 } 140 else if(!ptr) 141 { 142 Pop(top, p); 143 ptr = p->rchild; 144 } 145 146 } 147 } 148 else 149 return ERROR; 150 } 151 //格式需要 152 cout << endl; 153 return OK; 154 } 155 //中序遍历 156 Status InOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&)) 157 { 158 //中序遍历的总体思路: 159 //仔细观察会发现,其实先序遍历与中序遍历走的路线是完全一样的,唯一的区别在于节点的访问时机。 160 //在节点弹出时再对其进行访问。 161 BiTree ptr = T, p = NULL; 162 if(ptr) 163 { 164 //格式需要 165 cout << "先序遍历的结果为: "; 166 LinkList top = NULL; 167 Init_Stack(top); 168 Push(top, ptr); 169 ptr = ptr->lchild; 170 while(ptr || !StackEmpty(top)) 171 { 172 if(ptr) 173 { 174 Push(top, ptr); 175 ptr = ptr->lchild; 176 } 177 else if(!ptr) 178 { 179 Pop(top, p); 180 if(visit(p)) 181 { 182 ptr = p->rchild; 183 } 184 //访问失败 185 else 186 { 187 return ERROR; 188 } 189 } 190 } 191 } 192 //格式需要 193 cout << endl; 194 return OK; 195 } 196 //后序遍历 197 Status PostOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&)) 198 { 199 //后序遍历的思路: 200 //先对于先序与中序来说,后序的路线更为复杂。 201 //多了一个标志域;只有当该节点已经进入过栈中两次后才可以对其进行访问。 202 BiTree ptr = T, p = NULL; 203 if(ptr) 204 { 205 //格式需要 206 cout << "先序遍历的结果为: "; 207 LinkList top = NULL; 208 Init_Stack(top); 209 //表示该节点第一次被压入栈中 210 ptr->flag = 1; 211 Push(top, ptr); 212 ptr = ptr->lchild; 213 while(ptr || !StackEmpty(top)) 214 { 215 if(ptr) 216 { 217 ptr->flag = 1; 218 Push(top, ptr); 219 ptr = ptr->lchild; 220 } 221 else if(!ptr) 222 { 223 Pop(top, p); 224 if(p->flag == 1) 225 { 226 //表示该节点第二次入栈 227 p->flag = 2; 228 Push(top, p); 229 ptr = p->rchild; 230 } 231 //该节点已经进入过栈中两次 232 else 233 { 234 if(visit(p)) 235 { 236 //为了让下一次进入循环就直接出栈 237 ptr = NULL; 238 } 239 else 240 return ERROR; 241 } 242 } 243 } 244 245 } 246 //格式需要 247 cout << endl; 248 return OK; 249 } 250 //层次遍历 251 Status LevelOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&)) 252 { 253 //层次遍历的思路: 254 //从上到下、从左到右. 255 //一个节点要在其左右儿子(如果存在的话)都进入队列后,再出队列并立即对其进行访问. 256 BiTree ptr = T; 257 QueuePtr q = NULL; 258 if(ptr) 259 { 260 //格式需要 261 cout << "层次遍历的结果为: "; 262 LinkQueue Q; 263 InitQueue(Q); 264 EnQueue(Q, ptr); 265 while(!QueueEmpty(Q)) 266 { 267 //得到队首元素 268 //因为所使用的队列头文件GetHead函数参数类型有点冲突,所以此处需要拆一下包装。 269 //注意q的类型 270 GetHead(Q, q); 271 //如果队首的左儿子存在则入队列 272 if(q->Qdata->lchild) 273 { 274 EnQueue(Q, q->Qdata->lchild); 275 } 276 //如果ptr的右儿子存在则入队列 277 if(q->Qdata->rchild) 278 { 279 EnQueue(Q, q->Qdata->rchild); 280 } 281 //然后再删除队首元素并对其进行访问 282 DeQueue(Q, q->Qdata); 283 if(!visit(q->Qdata)) 284 { 285 //访问失败 286 return ERROR; 287 } 288 } 289 } 290 //格式需要 291 cout << endl; 292 return OK; 293 } 294 //销毁(清空)一颗(链式)二叉树 295 Status DestroyBiTree(BiTree& T) 296 { 297 if(T) 298 { 299 DestroyBiTree(T->lchild); 300 DestroyBiTree(T->rchild); 301 T = NULL; 302 } 303 return OK; 304 } 305 //判断一颗二叉树是否为空 306 Status BiTreeEmpty(const BiTree& T) 307 { 308 if(T) 309 { 310 return ERROR; 311 } 312 else 313 return TRUE; 314 } 315 //求二叉树的深度 316 Status BiTreeDepth(const BiTree& T) 317 { 318 int Depth = 0, LeftDepth = 0, RigthDepth = 0; 319 if(T) 320 { 321 LeftDepth = BiTreeDepth(T->lchild); 322 RigthDepth = BiTreeDepth(T->rchild); 323 Depth = 1 + (LeftDepth > RigthDepth ? LeftDepth : RigthDepth); 324 return Depth; 325 } 326 return 0; 327 } 328 //访问节点 329 Status Visit(const BiTree& p) 330 { 331 if(p) 332 { 333 cout << p->data << '\t'; 334 return OK; 335 } 336 else 337 return ERROR; 338 } 339 //比较两关键字是否相等 340 Status Compare(BiTree ptr1, TElemType ptr2) 341 { 342 if(ptr1->data == ptr2) 343 return TRUE; 344 else 345 return 0; 346 } 347 //查找节点所在处 348 BiTree Location(const BiTree& T, TElemType e, Status (*compare)(BiTree, TElemType)) 349 { 350 //模仿了一下层次遍历 351 BiTree ptr = T; 352 QueuePtr q = NULL; 353 if(ptr) 354 { 355 LinkQueue Q; 356 InitQueue(Q); 357 EnQueue(Q, ptr); 358 while(!QueueEmpty(Q)) 359 { 360 //得到队首元素 361 //因为所使用的队列头文件GetHead函数参数类型有点冲突,所以此处需要拆一下包装。 362 //注意q的类型 363 GetHead(Q, q); 364 //如果队首的左儿子存在则入队列 365 if(q->Qdata->lchild) 366 { 367 EnQueue(Q, q->Qdata->lchild); 368 } 369 //如果ptr的右儿子存在则入队列 370 if(q->Qdata->rchild) 371 { 372 EnQueue(Q, q->Qdata->rchild); 373 } 374 //然后再删除队首元素并对其进行访问 375 DeQueue(Q, q->Qdata); 376 if(compare(q->Qdata, e)) 377 { 378 return (q->Qdata); 379 } 380 } 381 } 382 return NULL; 383 } 384 385 386 387 /************************************************ 388 *文件名: Stack.h 389 *创建人: 水龙头 390 *日 期: 2019.7.20 391 *描 述: 链式栈(带表头) 392 ***********************************************/ 393 #ifndef STACK_H_INCLUDED 394 #define STACK_H_INCLUDED 395 396 397 398 #include<iostream> 399 #include "BiTree.h" 400 using namespace std; 401 #define TRUE 1 402 #define FALSE 0 403 #define ERROR -1 404 #define OK 1 405 #define OVERFLOW -2 406 #define INFEASIBLE -1 407 typedef BiTree SElemType; 408 typedef int Status; 409 typedef struct SNode 410 { 411 SElemType data; 412 struct SNode *next; 413 }SNode, *LinkList; 414 Status Init_Stack(LinkList &top); 415 Status Push(LinkList &top, SElemType ch); 416 Status Pop(LinkList &top, SElemType &e); 417 Status GetTop(const LinkList &top, SElemType &e); 418 Status DestroyStack(LinkList&); 419 Status ClearStack(LinkList&); 420 Status StackEmpty(const LinkList&); 421 Status StackLength(const LinkList&); 422 Status StackTraverse(const LinkList& , Status (*visit)(const LinkList&)); 423 Status Visit(const LinkList&); 424 425 #endif // STACK_H_INCLUDED 426 427 428 429 430 /************************************************ 431 *文件名: Stack.cpp 432 *创建人: 水龙头 433 *日 期: 2019.7.20 434 *描 述: 链式栈(带表头) 435 ***********************************************/ 436 #include "Stack.h" 437 Status GetTop(const LinkList &top, SElemType &e) //得到栈顶元素 438 { 439 if(top) 440 { 441 LinkList p = top; 442 if(!p->next) 443 { 444 return ERROR; 445 } 446 else 447 { 448 e = top->data; 449 return OK; 450 } 451 } 452 else 453 { 454 return INFEASIBLE; 455 } 456 } 457 Status DestroyStack(LinkList& top) 458 { 459 LinkList ptr = NULL; 460 while(top) 461 { 462 ptr = top; 463 top = top->next; 464 free(ptr); 465 } 466 return OK; 467 } 468 Status ClearStack(LinkList& top) 469 { 470 if(top) 471 { 472 LinkList ptr = NULL; 473 while(top->next) 474 { 475 ptr = top; 476 top = top->next; 477 free(ptr); 478 } 479 return OK; 480 } 481 else 482 return INFEASIBLE; 483 } 484 Status StackEmpty(const LinkList& top) 485 { 486 if(top) 487 { 488 if(top->next) 489 { 490 return FALSE; 491 } 492 else 493 return TRUE; 494 } 495 else 496 return INFEASIBLE; 497 } 498 Status StackLength(const LinkList& top) 499 { 500 if(top) 501 { 502 int count = 0; 503 LinkList ptr = top; 504 while(ptr->next) 505 { 506 ptr = ptr->next; 507 count++; 508 } 509 return count; 510 } 511 else 512 return INFEASIBLE; 513 } 514 Status StackTraverse(const LinkList& top, Status (*visit)(const LinkList&)) 515 { 516 if(top) 517 { 518 LinkList ptr = top; 519 while(ptr->next) 520 { 521 visit(ptr); 522 ptr = ptr->next; 523 } 524 return OK; 525 } 526 else 527 return INFEASIBLE; 528 } 529 Status Visit(const LinkList& ptr) 530 { 531 cout << ptr->data << '\t'; 532 return OK; 533 } 534 Status Init_Stack(LinkList &top) //初始化栈 535 { 536 LinkList p = (SNode *)malloc(sizeof(SNode)); 537 if(!p) 538 { 539 return OVERFLOW; 540 } 541 else 542 { 543 p->next = NULL; 544 top = p; 545 return OK; 546 } 547 } 548 Status Push(LinkList &top, SElemType ch) 549 { 550 if(top) 551 { 552 LinkList q = (SNode *)malloc(sizeof(SNode)); 553 if(!q) 554 { 555 return OVERFLOW; 556 } 557 else 558 { 559 q->next = top; //注意这一步是将头指针赋给新节点的后继 560 q->data = ch; 561 top = q; 562 return OK; 563 } 564 } 565 else 566 return INFEASIBLE; 567 } 568 Status Pop(LinkList &top,SElemType&e) //不能对字面值进行引用 569 { 570 if(top) 571 { 572 LinkList p = top; 573 if(!p->next) 574 { 575 return ERROR; 576 } 577 else 578 { 579 e = top->data; 580 top = top->next; 581 free(p); 582 return OK; 583 } 584 } 585 else 586 return INFEASIBLE; 587 } 588 589 590 591 592 /************************************************ 593 *文件名: Queue.h 594 *创建人: 水龙头 595 *日 期: 2019.7.14 596 *描 述: 链式队列 597 ***********************************************/ 598 #ifndef QUEUE_H_INCLUDED 599 #define QUEUE_H_INCLUDED 600 601 602 #include <iostream> 603 #include "BiTree.h" 604 using namespace std; 605 #define TRUE 1 606 #define FALSE 0 607 #define OK 1 608 #define ERROR -1 609 #define OVERFLOW -2 610 611 typedef BiTree QElemType; 612 typedef int Status; 613 typedef struct QNode 614 { 615 QElemType Qdata; 616 struct QNode* next; 617 }QNode, *QueuePtr; 618 typedef struct 619 { 620 QueuePtr front; //队首指针 621 QueuePtr rear; //队尾指针 622 }LinkQueue; 623 Status InitQueue(LinkQueue&); //初始化队列 624 Status DestroyQueue(LinkQueue&); //销毁队列 625 Status ClearQueue(LinkQueue&); //清空队列 626 Status QueueEmpty(const LinkQueue&); //判断队列是否为空 627 int QueueLength(const LinkQueue&); //返回队列长度 628 Status GetHead(const LinkQueue&, QueuePtr&); //返回队首元素 629 Status EnQueue(LinkQueue&, QElemType); //插入一个元素 630 Status DeQueue(LinkQueue&, QElemType&); //删除一个元素 631 Status QueueTraverse(const LinkQueue&, Status (*visit)(const QueuePtr )); //遍历整个队列 632 Status Visit(const QueuePtr); 633 634 635 636 #endif // QUEUE_H_INCLUDED 637 638 639 640 641 /************************************************ 642 *文件名:Queue.cpp 643 *创建人:水龙头 644 *日 期: 2019.7.14 645 *描 述: 链式队列 646 ***********************************************/ 647 #include "Queue.h" 648 649 Status InitQueue(LinkQueue& Q) 650 { 651 Q.front = Q.rear = new QNode; //带头节点的链式队列 652 if(Q.front) 653 { 654 Q.front->next = NULL; 655 return OK; 656 } 657 else 658 return OVERFLOW; 659 } 660 Status DestroyQueue(LinkQueue& Q) 661 { 662 while(Q.front) 663 { 664 Q.rear = Q.front->next; 665 delete (Q.front); //空间虽已销毁,但原本指向该空间的指针还在,只不过变为野指针了而已。 666 Q.front = Q.rear; 667 } 668 return OK; 669 } 670 Status ClearQueue(LinkQueue& Q) 671 { 672 QueuePtr ptr = Q.front->next; 673 Q.rear = Q.front; 674 while(ptr) 675 { 676 QueuePtr p = ptr; 677 ptr = ptr->next; 678 delete p; 679 } 680 return OK; 681 } 682 Status QueueEmpty(const LinkQueue& Q) 683 { 684 if(Q.front == Q.rear) 685 return TRUE; 686 else 687 return FALSE; 688 } 689 int QueueLength(const LinkQueue& Q) 690 { 691 if(Q.front == Q.rear) 692 return 0; 693 else 694 { 695 int count = 0; 696 QueuePtr ptr = Q.front->next; 697 while(ptr) 698 { 699 count++; 700 ptr = ptr->next; 701 } 702 return count; 703 } 704 } 705 Status GetHead(const LinkQueue& Q, QueuePtr& ptr) 706 { 707 QueuePtr p = Q.front->next; 708 if(p) 709 { 710 ptr = p; 711 return OK; 712 } 713 else 714 { 715 ptr = NULL; 716 return ERROR; 717 } 718 } 719 Status EnQueue(LinkQueue& Q, QElemType e) 720 { 721 QueuePtr ptr = new QNode; 722 if(ptr) 723 { 724 ptr->next = NULL; 725 ptr->Qdata = e; 726 Q.rear->next = ptr; 727 Q.rear = ptr; 728 return OK; 729 } 730 else 731 return OVERFLOW; 732 } 733 Status DeQueue(LinkQueue& Q, QElemType& e) 734 { 735 if(Q.front == Q.rear) 736 return ERROR; 737 else //注意这是队列,只能从队首删除元素,从队尾插入元素 738 { 739 QueuePtr ptr = Q.front->next; 740 Q.front->next = ptr->next; 741 e = ptr->Qdata; 742 if(ptr == Q.rear) //如果原本队列里只有一个元素 743 { 744 Q.rear = Q.front; 745 } 746 delete ptr; 747 return OK; 748 } 749 } 750 Status Visit(const QueuePtr ptr) 751 { 752 if(!ptr) 753 { 754 return ERROR; 755 } 756 else 757 { 758 cout << ptr->Qdata << '\t'; 759 return OK; 760 } 761 } 762 Status QueueTraverse(const LinkQueue& Q, Status (*visit)(const QueuePtr )) 763 { 764 QueuePtr ptr = NULL; 765 if(Q.front == Q.rear) 766 return ERROR; 767 else 768 { 769 ptr = Q.front->next; //从第一个节点开始遍历(带头节点的链表) 770 while(ptr) 771 { 772 (*visit)(ptr); 773 ptr = ptr->next; 774 } 775 cout << endl; 776 return OK; 777 } 778 }