1 //二叉树问题集:
   2 //20140822
   3 
   4 #include <iostream>
   5 #include <cstdio>
   6 #include <cstdlib>
   7 #include <queue>
   8 #include <stack>
   9 #include <list>
  10 using namespace std;
  11 
  12 
  13 typedef int ElementType;
  14 typedef struct TreeNode
  15 {
  16     ElementType data;
  17     struct TreeNode* pLeft;
  18     struct TreeNode* pRight;
  19 }TreeNode;
  20 
  21 typedef struct TreeNode* PtrNode;
  22 typedef struct TreeNode* BinaryTree;
  23 
  24 
  25 //建立二叉树:
  26 PtrNode CreateBinaryTreeNode(ElementType val)
  27 {
  28     PtrNode ptrNode = new TreeNode;
  29     ptrNode->data = val;
  30     ptrNode->pLeft = NULL;
  31     ptrNode->pRight = NULL;
  32     return ptrNode;
  33 }
  34 
  35 void ConnectTreeNodes(PtrNode pNode1, PtrNode pNode2, PtrNode pNode3)
  36 {
  37     if (pNode1 == NULL)
  38     {
  39         return ;
  40     }
  41     pNode1->pLeft = pNode2;
  42     pNode1->pRight = pNode3;
  43 }
  44 
  45 BinaryTree CreateBinaryTree()
  46 {
  47     PtrNode pNode1 = CreateBinaryTreeNode(1);
  48     PtrNode pNode2 = CreateBinaryTreeNode(2);
  49     PtrNode pNode3 = CreateBinaryTreeNode(3);
  50     PtrNode pNode4 = CreateBinaryTreeNode(4);
  51     PtrNode pNode5 = CreateBinaryTreeNode(5);
  52     PtrNode pNode6 = CreateBinaryTreeNode(6);
  53     PtrNode pNode7 = CreateBinaryTreeNode(7);
  54     PtrNode pNode8 = CreateBinaryTreeNode(8);
  55     PtrNode pNode9 = CreateBinaryTreeNode(9);
  56     PtrNode pNode10 = CreateBinaryTreeNode(10);
  57     PtrNode pNode11 = CreateBinaryTreeNode(11);
  58     PtrNode pNode12 = CreateBinaryTreeNode(12);
  59 
  60     ConnectTreeNodes(pNode1, pNode2, pNode3);
  61     ConnectTreeNodes(pNode2, pNode4, pNode5);
  62     ConnectTreeNodes(pNode3, pNode6, pNode7);
  63     ConnectTreeNodes(pNode4, pNode8, pNode9);
  64     ConnectTreeNodes(pNode8, pNode10, pNode11);
  65 
  66     return pNode1;
  67 }
  68 BinaryTree CreateBinaryTree2()
  69 {
  70     PtrNode pNode1 = CreateBinaryTreeNode(1);
  71     PtrNode pNode2 = CreateBinaryTreeNode(2);
  72     PtrNode pNode3 = CreateBinaryTreeNode(3);
  73     PtrNode pNode4 = CreateBinaryTreeNode(4);
  74     PtrNode pNode5 = CreateBinaryTreeNode(5);
  75     PtrNode pNode6 = CreateBinaryTreeNode(6);
  76     PtrNode pNode7 = CreateBinaryTreeNode(7);
  77     PtrNode pNode8 = CreateBinaryTreeNode(8);
  78     PtrNode pNode9 = CreateBinaryTreeNode(9);
  79     PtrNode pNode10 = CreateBinaryTreeNode(10);
  80     PtrNode pNode11 = CreateBinaryTreeNode(11);
  81     PtrNode pNode12 = CreateBinaryTreeNode(12);
  82 
  83     ConnectTreeNodes(pNode1, pNode2, pNode3);
  84     ConnectTreeNodes(pNode2, pNode4, pNode5);
  85     ConnectTreeNodes(pNode3, pNode6, pNode7);
  86     ConnectTreeNodes(pNode4, pNode8, pNode9);
  87     ConnectTreeNodes(pNode8, pNode10, NULL);
  88 
  89     return pNode1;
  90 }
  91 
  92 BinaryTree CreateBinaryTree3()
  93 {
  94     PtrNode pNode1 = CreateBinaryTreeNode(10);
  95     PtrNode pNode2 = CreateBinaryTreeNode(5);
  96     PtrNode pNode3 = CreateBinaryTreeNode(12);
  97     PtrNode pNode4 = CreateBinaryTreeNode(4);
  98     PtrNode pNode5 = CreateBinaryTreeNode(7);
  99     ConnectTreeNodes(pNode1, pNode2, pNode3);
 100     ConnectTreeNodes(pNode2, pNode4, pNode5);
 101 
 102     return pNode1;
 103 }
 104 
 105 BinaryTree CreateBinaryTree4()
 106 {
 107     PtrNode pNode1 = CreateBinaryTreeNode(1);
 108     PtrNode pNode2 = CreateBinaryTreeNode(2);
 109     PtrNode pNode3 = CreateBinaryTreeNode(3);
 110     PtrNode pNode4 = CreateBinaryTreeNode(4);
 111     PtrNode pNode5 = CreateBinaryTreeNode(5);
 112     PtrNode pNode6 = CreateBinaryTreeNode(6);
 113     PtrNode pNode7 = CreateBinaryTreeNode(7);
 114     PtrNode pNode8 = CreateBinaryTreeNode(8);
 115     PtrNode pNode9 = CreateBinaryTreeNode(9);
 116     PtrNode pNode10 = CreateBinaryTreeNode(10);
 117     PtrNode pNode11 = CreateBinaryTreeNode(11);
 118     PtrNode pNode12 = CreateBinaryTreeNode(12);
 119 
 120     //ConnectTreeNodes(pNode1, pNode2, pNode3);
 121     //ConnectTreeNodes(pNode2, pNode4, pNode5);
 122     ConnectTreeNodes(pNode3, pNode6, pNode7);
 123     ConnectTreeNodes(pNode4, pNode8, pNode9);
 124     //ConnectTreeNodes(pNode8, pNode10, pNode11);
 125 
 126     return pNode1;
 127 }
 128 
 129 //先序遍历:递归
 130 void PerOrderPrint(BinaryTree Tree)
 131 {
 132     if (Tree == NULL)
 133     {
 134         return ;
 135     }
 136 
 137     cout << Tree->data << " ";
 138     PerOrderPrint(Tree->pLeft);
 139     PerOrderPrint(Tree->pRight);
 140 
 141 }
 142 
 143 //中序遍历:递归
 144 void InOrderPrint(BinaryTree Tree)
 145 {
 146     if (Tree == NULL)
 147     {
 148         return;
 149     }
 150     InOrderPrint(Tree->pLeft);
 151     cout << Tree->data << " ";
 152     InOrderPrint(Tree->pRight);
 153 }
 154 
 155 //后序遍历:递归
 156 void PostOrderPrint(BinaryTree Tree)
 157 {
 158     if (Tree == NULL)
 159     {
 160         return;
 161     }
 162     PostOrderPrint(Tree->pLeft);
 163     PostOrderPrint(Tree->pRight);
 164     cout << Tree->data << " ";
 165 }
 166 
 167 /************************************************************************/
 168 /* 二叉树的非递归遍历:先序,中序、后序、及层序遍历
 169 /************************************************************************/
 170 /************************************************************************
 171 * 非递归先序遍历:
 172 * 方法:用栈结构,
 173 *    1.先让右子树节点进栈,再让左子树节点进栈
 174 *    2.如果栈非空,则进行出栈操作
 175 *    类似于层序遍历
 176 ************************************************************************/
 177 void PerOrderPrintNoRecursive(BinaryTree Tree)
 178 {
 179     if (Tree == NULL)
 180     {
 181         return;
 182     }
 183     PtrNode ptrNode = Tree;
 184     stack<PtrNode> s;
 185     s.push(ptrNode);
 186     while (!s.empty())
 187     {
 188         ptrNode = s.top();
 189         cout << ptrNode->data << " ";
 190         s.pop();
 191         if (ptrNode->pRight != NULL) //注意:先序遍历先让右子树节点入栈
 192         {
 193             s.push(ptrNode->pRight);
 194         }
 195         if (ptrNode->pLeft != NULL)
 196         {
 197             s.push(ptrNode->pLeft);
 198         }
 199     }
 200 }
 201 
 202 
 203 /************************************************************************
 204 * 非递归中序遍历:
 205 * 方法:用栈结构,
 206 *    1.
 207 *    2.
 208 ************************************************************************/
 209 void InOrderPrintNoRecursive(BinaryTree Tree)
 210 {
 211     if (Tree == NULL)
 212     {
 213         return;
 214     }
 215 
 216     PtrNode ptrCurrent = Tree; //指明当前要检测的数据,此时根节点不要先入栈
 217     stack<PtrNode> s;
 218     while (ptrCurrent != NULL || !s.empty())
 219     {
 220         while (ptrCurrent != NULL)
 221         {
 222             s.push(ptrCurrent);
 223             ptrCurrent = ptrCurrent->pLeft;
 224         }
 225         if (!s.empty())
 226         {
 227             ptrCurrent = s.top();
 228             cout << ptrCurrent->data << " ";
 229             s.pop();
 230             ptrCurrent = ptrCurrent->pRight;
 231         }
 232     }
 233 }
 234 
 235 
 236 /************************************************************************
 237 * 非递归后序遍历:
 238 * 方法:用栈结构,
 239 ************************************************************************/
 240 //void PostOrderNoRecursive(BinaryTree Tree)
 241 //{
 242 //    if (Tree == NULL)
 243 //    {
 244 //        return ;
 245 //    }
 246 
 247 //    PtrNode ptrCurr = Tree;
 248 //    stack<PtrNode> s;
 249 //    s.push(ptrCurr);
 250 //    while (ptrCurr != NULL || !s.empty())
 251 //    {
 252 //        while (ptrCurr != NULL)
 253 //        {
 254 //            ptrCurr = s.top();
 255 //            if (ptrCurr->pLeft != NULL)
 256 //            {
 257 //                s.push(ptrCurr->pLeft);
 258 //            }
 259 //            if (ptrCurr->pRight != NULL)
 260 //            {
 261 //                s.push(ptrCurr->pRight);
 262 //            }
 263 //        }
 264 
 265 //    }
 266 
 267 //}
 268 
 269 
 270 
 271 //层序遍历二叉树
 272 void LayerOrderPrint(BinaryTree Tree)
 273 {
 274     if (Tree == NULL)
 275     {
 276         return ;
 277     }
 278 
 279     int nodeNumInTree = 0; //  记录节点的个数
 280     queue<PtrNode> Queue;
 281     PtrNode ptrNode = Tree;
 282     Queue.push(ptrNode);
 283     while (!Queue.empty())
 284     {
 285         ptrNode = Queue.front();
 286         cout << ptrNode->data << " " ;
 287         nodeNumInTree++;
 288         Queue.pop();
 289         if (ptrNode->pLeft != NULL)
 290         {
 291             Queue.push(ptrNode->pLeft);
 292         }
 293         if (ptrNode->pRight != NULL)
 294         {
 295             Queue.push(ptrNode->pRight);
 296         }
 297     }
 298 
 299     //cout << endl;
 300     //cout << "节点的个数: " << nodeNumInTree;
 301 
 302     return ;
 303 }
 304 
 305 
 306 //求书中结点的个数
 307 int GetNodeNumber(BinaryTree Tree)
 308 {
 309     if (Tree == NULL)
 310     {
 311         return 0;
 312     }
 313     return GetNodeNumber(Tree->pLeft) + GetNodeNumber(Tree->pRight) + 1;
 314 }
 315 
 316 //求叶子节点的个数:
 317 int GetLeavesNumber(BinaryTree Tree)
 318 {
 319     if (Tree == NULL)
 320     {
 321         return 0;
 322     }
 323     static int leavesNum = 0;
 324 
 325     if (Tree->pLeft == NULL && Tree->pRight == NULL)
 326     {
 327         leavesNum++;
 328     }
 329     GetLeavesNumber(Tree->pLeft);
 330     GetLeavesNumber(Tree->pRight);
 331 
 332     return leavesNum;
 333 }
 334 
 335 //求二叉树深度
 336 int GetTreeDepth(BinaryTree Tree)
 337 {
 338     if (Tree == NULL)
 339     {
 340         return 0;
 341     }
 342     int leftDepth = GetTreeDepth(Tree->pLeft);
 343     int rightDepth = GetTreeDepth(Tree->pRight);
 344 
 345     return leftDepth >= rightDepth?leftDepth+1:rightDepth+1;
 346 }
 347 
 348 //将二叉树变为有序的双向链表 剑指offer27题
 349 void ConvertToDoubleList(BinaryTree Tree, PtrNode* listNode);
 350 BinaryTree ConvertToList(BinaryTree Tree)
 351 {
 352     if (Tree == NULL)
 353     {
 354         return NULL;
 355     }
 356 
 357     PtrNode listNode = NULL;
 358     ConvertToDoubleList(Tree, &listNode);
 359 
 360     //返回头结点:
 361     PtrNode lastNode = listNode;
 362     while (lastNode != NULL && lastNode->pLeft != NULL)
 363     {
 364         lastNode = lastNode->pLeft;
 365     }
 366 
 367 
 368 
 369     return lastNode;
 370 }
 371 void ConvertToDoubleList(BinaryTree Tree, PtrNode* listNode)
 372 {
 373     if (Tree == NULL)
 374     {
 375         return ;
 376     }
 377 
 378     PtrNode pCurrent = Tree;
 379     if (pCurrent->pLeft != NULL)
 380     {
 381         ConvertToDoubleList(pCurrent->pLeft, listNode);
 382     }
 383 
 384     pCurrent->pLeft = *listNode;
 385     if (*listNode != NULL)
 386     {
 387         (*listNode)->pRight = pCurrent;
 388     }
 389     *listNode = pCurrent;
 390 
 391     if (pCurrent->pRight != NULL)
 392     {
 393         ConvertToDoubleList(pCurrent->pRight, listNode);
 394     }
 395 }
 396 
 397 void PrintList(BinaryTree ListTree)
 398 {
 399     if (ListTree == NULL)
 400     {
 401         return;
 402     }
 403     PtrNode p = ListTree;
 404     while (p != NULL)
 405     {
 406         cout << p->data << " ";
 407         p = p->pRight;
 408     }
 409     cout << endl;
 410 }
 411 //转换成双向链表完
 412 
 413 
 414 /*********************************************************
 415 * 求二叉树第K层的节点数
 416 * 1.如果树为空或者K<1,返回0
 417 * 2.如果K == 1, 返回1
 418 * 3.如果K>1, 节点数等于左子树第K-1层节点与右子树第K-1层之和
 419 **********************************************************/
 420 //递归
 421 int GetNodeNumInLayerK(BinaryTree Tree, int k)
 422 {
 423     if (Tree == NULL || k < 1)
 424     {
 425         return 0;
 426     }
 427     if (k == 1)
 428     {
 429         return 1;
 430     }
 431 
 432     return GetNodeNumInLayerK(Tree->pLeft, k - 1) + GetNodeNumInLayerK(Tree->pRight, k - 1);
 433 }
 434 //非递归,根据层序遍历,求出第K层节点数
 435 int GetNodeNumInLayerKByLayerPrint(BinaryTree Tree, int k)
 436 {
 437     if (Tree == NULL || k < 1)
 438     {
 439         return 0;
 440     }
 441 //    if (k == 1)
 442 //    {
 443 //        return 1;
 444 //    }
 445 
 446     PtrNode ptrNode = Tree;
 447     queue<PtrNode> q;
 448     q.push(ptrNode);
 449     while (q.size())
 450     {
 451         --k;
 452         if (k <= 0) break;
 453         int nodeNumInQ = q.size();
 454         while (nodeNumInQ--)
 455         {
 456             ptrNode = q.front();
 457             q.pop();
 458             if (ptrNode->pLeft != NULL)
 459             {
 460                 q.push(ptrNode->pLeft);
 461             }
 462             if (ptrNode->pRight != NULL)
 463             {
 464                 q.push(ptrNode->pRight);
 465             }
 466         }
 467     }
 468     return q.size();
 469 }
 470 
 471 
 472 /*********************************************************
 473 * 判断两个树结构是否结构相同 
 474 * 1.如果两个树都为空,返回true;
 475 * 2.如果一个为空,一个不为空, 返回flase
 476 * 3.如果都不为空, 则判断对应的左右子树是否结构相同, 
 477 **********************************************************/
 478 bool StructureCmp(BinaryTree Tree1, BinaryTree Tree2)
 479 {
 480     if (Tree1 == NULL && Tree2 == NULL)
 481     {
 482         return true;
 483     }
 484     if (Tree1 == NULL && Tree2 != NULL || Tree1 != NULL && Tree2 == NULL)
 485     {
 486         return false;
 487     }
 488 
 489     bool left = StructureCmp(Tree1->pLeft, Tree2->pLeft);
 490     bool right = StructureCmp(Tree1->pRight, Tree2->pRight);
 491     return (left && right);
 492 }
 493 
 494 
 495 /*********************************************************
 496 * 判断树的子结构 
 497 * 输入两个树A和B,判断树B是否是树A的子结构
 498 * 1.如果两个树都为空,返回false;
 499 * 2.如果一个为空,一个不为空, 返回flase
 500 * 3.如果都不为空, 则判断对应的是否是子结构, 
 501 * 4.步骤:
 502 *    1)在A中找到和B的根节点的值相同的节点R
 503 *    2)判断树A中以R为根节点的子树是不是包含和树B一样的结构
 504 * 剑指offer,第18题
 505 **********************************************************/
 506 bool DoesTreeAHaveTreeB(BinaryTree TreeA, BinaryTree TreeB);
 507 bool HasSubtree(BinaryTree TreeA, BinaryTree TreeB)
 508 {
 509     bool result = false;
 510     if (TreeA != NULL && TreeB != NULL)
 511     {
 512         if (TreeA->data == TreeB->data)
 513         {
 514             result = DoesTreeAHaveTreeB(TreeA,TreeB);
 515         }
 516         if (!result)
 517         {
 518             result = HasSubtree(TreeA->pLeft, TreeB);
 519         }
 520         if (!result)
 521         {
 522             result = HasSubtree(TreeA->pRight, TreeB);
 523         }
 524     }
 525     return result;
 526 }
 527 
 528 bool DoesTreeAHaveTreeB(BinaryTree TreeA, BinaryTree TreeB)
 529 {
 530     if (TreeA == NULL)
 531     {
 532         return false;
 533     }
 534     if (TreeB == NULL)
 535     {
 536         return true;
 537     }
 538 
 539     return DoesTreeAHaveTreeB(TreeA->pLeft, TreeB->pLeft) && DoesTreeAHaveTreeB(TreeA->pRight, 
 540         TreeB->pRight);
 541 }
 542 
 543 
 544 
 545 
 546 /*********************************************************
 547 * 判断树是否是平衡二叉树
 548 * 1.如果树为空,返回true;
 549 * 2.如果不为空, 则判断左右子树是否都是AVL,且左右子树高度相差不大于1,则返回true,其他返回false, 
 550 **********************************************************/
 551 bool IsAVL(BinaryTree Tree, int& Height)
 552 {
 553     if (Tree == NULL)
 554     {
 555         return true;
 556     }
 557 
 558     int leftHeight = 0;
 559     int rightHeight = 0;
 560     bool isLeftAVL = IsAVL(Tree->pLeft, leftHeight);
 561     bool isRightAVL = IsAVL(Tree->pRight, rightHeight);
 562     Height = leftHeight >= rightHeight?leftHeight+1:rightHeight+1;
 563 
 564     if (isLeftAVL && isRightAVL && abs(leftHeight - rightHeight) <= 1)
 565     {
 566         return true;
 567     }
 568     else
 569     {
 570         return false;
 571     }
 572 
 573 }
 574 
 575 
 576 
 577 /*********************************************************
 578 * 求二叉树的镜像 
 579 * 1.左右子树交换;
 580 **********************************************************/
 581 void TreeMirror(BinaryTree Tree)
 582 {
 583     if (Tree == NULL)
 584     {
 585         return ;
 586     }
 587     PtrNode ptrNode = NULL;
 588     ptrNode = Tree->pLeft;
 589     Tree->pLeft = Tree->pRight;
 590     Tree->pRight = ptrNode;
 591 
 592     TreeMirror(Tree->pLeft);
 593     TreeMirror(Tree->pRight);
 594 }
 595 
 596 /*********************************************************
 597 * 重建二叉树
 598 * 根据二叉树的先序及中序遍历,重建二叉树
 599 * 剑指offer 6题;编程之美3.9
 600 **********************************************************/
 601 PtrNode ConstructBinaryTree(int* startPerOrder, int* endPerOrder, int* startInOrder, int* endInOrder);
 602 BinaryTree RebuildTree(int* PerOrder, int* InOrder, int length)
 603 {
 604     if (PerOrder == NULL || InOrder == NULL || length <= 0)
 605     {
 606         return NULL;
 607     }
 608 
 609     BinaryTree rebuildTree = NULL;
 610     rebuildTree = ConstructBinaryTree(PerOrder, PerOrder+length-1, InOrder, InOrder+length-1);
 611 
 612     return rebuildTree;
 613 }
 614 PtrNode ConstructBinaryTree(int* startPerOrder, int* endPerOrder, int* startInOrder, int* endInOrder)
 615 {
 616     PtrNode rootNode = new TreeNode; 
 617     rootNode->pLeft = rootNode->pRight = NULL;
 618     rootNode->data = startPerOrder[0];
 619 
 620     int* ptrInOrder = startInOrder;
 621     while (*ptrInOrder != rootNode->data && ptrInOrder <= endInOrder)
 622         ++ptrInOrder;
 623     int leftLen = ptrInOrder - startInOrder;
 624 
 625     if (leftLen > 0)
 626     {
 627         rootNode->pLeft = ConstructBinaryTree(startPerOrder+1, startPerOrder+leftLen,
 628             startInOrder, startInOrder+leftLen-1);
 629     }
 630     if (leftLen < endPerOrder - startPerOrder)
 631     {
 632         rootNode->pRight = ConstructBinaryTree(startPerOrder+leftLen+1, endPerOrder,
 633             startInOrder+leftLen+1, endInOrder);
 634     }
 635 
 636     return rootNode;
 637 }
 638 
 639 
 640 
 641 /*********************************************************
 642 * 找最低公共祖先 
 643 * 1.如果两个节点为根节点的左右子节点,则返回根节点
 644 * 2.如果都在左子树,则递归处理左子树,如果都在右子树,则递归处理右子树
 645 **********************************************************/
 646 bool FindNode(BinaryTree Tree, PtrNode pNode)
 647 {
 648     if (Tree == NULL)
 649     {
 650         return false;
 651     }
 652     if (Tree == pNode)
 653     {
 654         return true;
 655     }
 656     bool found = FindNode(Tree->pLeft, pNode);
 657     if (!found)
 658     {
 659         found = FindNode(Tree->pRight, pNode);
 660     }
 661 
 662     return found;
 663 }
 664 PtrNode GetLastCommonParent(BinaryTree Tree, PtrNode pNode1, PtrNode pNode2)
 665 {
 666     if (Tree == NULL || pNode1 == NULL || pNode2 == NULL)
 667     {
 668         return NULL;
 669     }
 670     if (FindNode(Tree->pLeft, pNode1))
 671     {
 672         if (FindNode(Tree->pRight, pNode2))
 673         {
 674             return Tree;
 675         }
 676         else
 677             return GetLastCommonParent(Tree->pLeft, pNode1, pNode2);
 678     }
 679     else if (FindNode(Tree->pRight, pNode1))
 680     {
 681         if (FindNode(Tree->pLeft, pNode2))
 682         {
 683             return Tree;
 684         }
 685         else
 686             return GetLastCommonParent(Tree->pRight, pNode1, pNode2);
 687     }
 688 }
 689 
 690 //递归解法二:
 691 PtrNode GetLCA(BinaryTree Tree, PtrNode pNode1, PtrNode pNode2)
 692 {
 693     if (Tree == NULL)
 694     {
 695         return NULL;
 696     }
 697     if (Tree == pNode1 || Tree == pNode2)
 698     {
 699         return Tree;
 700     }
 701     
 702     PtrNode leftNode = GetLCA(Tree->pLeft, pNode1, pNode2);
 703     PtrNode rightNode = GetLCA(Tree->pRight, pNode1, pNode2);
 704 
 705     if (leftNode != NULL && rightNode != NULL)
 706     {
 707         return Tree;
 708     }
 709     else if (leftNode != NULL)
 710     {
 711         return leftNode;
 712     }
 713     else if (rightNode != NULL)
 714     {
 715         return rightNode;
 716     }
 717     else
 718         return NULL;
 719 }
 720 
 721 //非递归解法:先求出两个节点从根节点开始的路径,然后比较路径节点,最后一个相同的就是公共祖先节点
 722 bool GetNodePath(BinaryTree Tree, PtrNode pNode, list<PtrNode>& path)
 723 {
 724     if (Tree == NULL)
 725     {
 726         return false;
 727     }
 728     path.push_back(Tree);
 729     if (Tree == pNode)
 730     {
 731         return true;
 732     }
 733 
 734     bool found = GetNodePath(Tree->pLeft, pNode, path);
 735     if (!found)
 736     {
 737         found = GetNodePath(Tree->pRight, pNode, path);
 738     }
 739 
 740     if (!found)
 741     {
 742         path.pop_back();
 743     }
 744 
 745     return found;
 746 }
 747 PtrNode GetLastCommonParentNoRecur(BinaryTree Tree, PtrNode pNode1, PtrNode pNode2)
 748 {
 749     if (Tree == NULL)
 750     {
 751         return NULL;
 752     }
 753     list<PtrNode> path1;
 754     bool foundNode1 = GetNodePath(Tree, pNode1, path1);
 755     list<PtrNode> path2;
 756     bool foundNode2 = GetNodePath(Tree, pNode2, path2);
 757     if (!foundNode1 || !foundNode2)
 758     {
 759         return NULL;
 760     }
 761 
 762     PtrNode lastCommonNode = NULL;
 763     list<PtrNode>::iterator iter1 = path1.begin();
 764     list<PtrNode>::iterator iter2 = path2.begin();
 765     while (iter1 != path1.end() && iter2 != path2.end())
 766     {
 767         if (*iter1 == *iter2)
 768         {
 769             lastCommonNode = *iter1;
 770         }
 771         else
 772             break;
 773         iter1++;
 774         iter2++;
 775     }
 776     return lastCommonNode;
 777 }
 778 
 779 
 780 
 781 /*********************************************************
 782 * 求二叉树中节点的最大距离
 783 * 1.如果为空,则最大距离就为0,同时左右子树的最大深度为0
 784 * 2.如果不为空,则最大距离要么是左子树最大深度,要么是右子树
 785 *    最大深度,要么是左右子树最大深度之和,同时记录左右
 786 *    子树的最大深度
 787 * 剑指offer;编程之美3.8
 788 **********************************************************/
 789 int GetLargestDestInNode(BinaryTree Tree, int& nMaxLeft, int& nMaxRight)
 790 {
 791     if (Tree == NULL)
 792     {
 793         nMaxLeft = 0;
 794         nMaxRight = 0;
 795         return 0;
 796     }
 797     int maxLL = 0, maxLR = 0;
 798     int maxRL = 0, maxRR = 0;
 799     int maxDistLeft = 0;
 800     int maxDistRight = 0;
 801     if (Tree->pLeft == NULL)
 802     {
 803         maxDistLeft = 0;
 804         nMaxLeft = 0;
 805     }
 806     if (Tree->pRight == NULL)
 807     {
 808         maxDistRight = 0;
 809         nMaxRight = 0;
 810     }
 811 
 812     if(Tree->pLeft != NULL)
 813     {
 814         maxDistLeft = GetLargestDestInNode(Tree->pLeft, maxLL, maxLR);
 815         nMaxLeft = maxLL>maxLR?maxLL+1:maxLR+1;
 816     }
 817     if(Tree->pRight != NULL)
 818     {
 819         maxDistRight = GetLargestDestInNode(Tree->pRight, maxRL, maxRR);
 820         nMaxRight = maxRL>maxRR?maxRL+1:maxRR+1;
 821     }
 822 
 823     int maxDist = maxDistLeft>maxDistRight?maxDistLeft:maxDistRight;
 824     int nMax = nMaxLeft + nMaxRight;
 825     return maxDist>nMax?maxDist:nMax;
 826 }
 827 
 828 /*********************************************************
 829 * 求二叉树中和为某一值得路径
 830 * 路径:从根节点到叶子节点的路径
 831 * 1.如果树为空,则路径为空
 832 * 2.如果树不为空,则从根节点开始遍历(即前序遍历),遍历的过程中记录路径
 833 *    并记录遍历过的路径的和,如果遍历到叶子节点,判断和是否为所给值,
 834 *    如果是,则输出此路径,然后再回到上一个节点。
 835 *    记录节点的路径就是一个栈结构,
 836 * 注意:在回到上一个几点时,要将叶子节点出栈
 837 * 另:本题用vector实现,是因为需要打印路径时,stack无法遍历打印
 838 * 剑指offer25题
 839 **********************************************************/
 840 void GetRoad(BinaryTree Tree, vector<int>& path, const int& expectedSum, int& currentSum);
 841 void GetRoad(BinaryTree Tree, int expectedSum)
 842 {
 843     if (Tree == NULL)
 844     {
 845         return;
 846     }
 847     vector<int> path;
 848     int currentSum = 0;
 849     GetRoad(Tree, path, expectedSum, currentSum);
 850     return ;
 851 }
 852 void GetRoad(BinaryTree Tree, vector<int>& path, const int& expectedSum, int& currentSum)
 853 {
 854     if (Tree == NULL)
 855     {
 856         return ;
 857     }
 858 
 859     path.push_back(Tree->data);
 860     currentSum += Tree->data;
 861     bool isLeaf = Tree->pLeft == NULL && Tree->pRight == NULL;
 862     if (isLeaf && expectedSum == currentSum)
 863     {
 864         cout << "和为" << expectedSum << "的路径为: ";
 865         vector<int>::iterator iter = path.begin();
 866         for (; iter != path.end(); ++iter)
 867         {
 868             cout << *iter << " ";
 869         }
 870         cout << endl;
 871     }
 872 
 873     GetRoad(Tree->pLeft, path, expectedSum, currentSum);
 874     GetRoad(Tree->pRight, path, expectedSum, currentSum);
 875 
 876     if (!path.empty())
 877     {
 878         //在返回父节点之前,应该从currentSum中减去当前节点的值,因为函数传递的参数currentSum是以引用传递的
 879         //若currentSum是非引用传递而是一般传值(即int currentSum),则不用这步操作
 880         currentSum -= path.back(); 
 881     }
 882     path.pop_back(); //在返回到父节点之前,删除路径上当前的节点
 883 }
 884 
 885 
 886 /*********************************************************
 887 * 判断二叉树是否是完全二叉树
 888 * 1.如果树为空,则返回true
 889 * 2.如果树不为空,则从根据层序遍历,遍历到第一个左子树为空的节点
 890 *    第一个左子树为空的节点的右子树也为空,并且其以后的所有节点
 891 *    的左右字数均为空的话,则为完全二叉树,返回true
 892 *    否则,不是完全二叉树,返回false
 893 **********************************************************/
 894 bool IsCompleteBinaryTree(BinaryTree Tree)
 895 {
 896     if (Tree == NULL)
 897     {
 898         return true;
 899     }
 900 
 901     queue<PtrNode> q;
 902     PtrNode ptrNode = Tree;
 903     q.push(ptrNode);
 904     
 905     PtrNode ptrFirNode = NULL;
 906     while (!q.empty())
 907     {
 908         ptrNode = q.front();
 909         if (ptrFirNode != NULL && (ptrNode->pLeft != NULL || ptrNode->pRight != NULL))
 910         {
 911             return false;
 912         }
 913         if (ptrFirNode == NULL && (ptrNode->pLeft == NULL || ptrNode->pRight == NULL))
 914         {
 915             ptrFirNode = ptrNode;
 916         }
 917         q.pop();
 918 
 919         if (ptrNode->pLeft != NULL)
 920         {
 921             q.push(ptrNode->pLeft);
 922         }
 923         if (ptrNode->pRight != NULL)
 924         {
 925             q.push(ptrNode->pRight);
 926         }
 927     }
 928 
 929     return true;
 930 }
 931 
 932 
 933 
 934 
 935 int main()
 936 {
 937     cout << "建立二叉树..." << endl;
 938     BinaryTree Tree = CreateBinaryTree();
 939     BinaryTree Tree2 = CreateBinaryTree2();
 940     BinaryTree Tree4 = CreateBinaryTree4();
 941 
 942 
 943     int treeDepth = GetTreeDepth(Tree);
 944     cout << "二叉树深度: " << treeDepth << endl;
 945 
 946     int nodeNum = GetNodeNumber(Tree);
 947     cout << "二叉树结点个数: " << nodeNum << endl;
 948 
 949     cout << "先序遍历..." << endl;
 950     PerOrderPrint(Tree);
 951     cout << endl;
 952 
 953     cout << "非递归先序遍历..." << endl;
 954     PerOrderPrintNoRecursive(Tree);
 955     cout << endl;
 956 
 957     cout << "中序遍历..." << endl;
 958     InOrderPrint(Tree);
 959     cout << endl;
 960 
 961     cout << "非递归中序遍历..." << endl;
 962     InOrderPrintNoRecursive(Tree);
 963     cout << endl;
 964 
 965     cout << "非递归后序遍历..." << endl;
 966     //PostOrderNoRecursive(Tree);
 967     cout << endl;
 968 
 969     cout << "层序遍历..." << endl;
 970     LayerOrderPrint(Tree);
 971     cout << endl;
 972 
 973     //int nodeNum = GetNodeNumber(Tree);
 974     //cout << "二叉树结点个数: " << nodeNum << endl;
 975 
 976 
 977     int leavesNum = GetLeavesNumber(Tree);
 978     cout << "叶节点的个数: " << leavesNum << endl;
 979 
 980 //    //转换成双向链表
 981 //    PtrNode treeToList = ConvertToList(Tree);
 982 //    cout << "双向链表由左至右打印:" <<endl;
 983 //    PrintList(treeToList);
 984 
 985     //第K层的节点数
 986     int k = 3;
 987     //int nodeNumInK = GetNodeNumInLayerK(Tree, k) - GetNodeNumInLayerK(Tree, k - 1);
 988     int nodeNumInK = GetNodeNumInLayerK(Tree, k);
 989     cout << "" << k << "层节点数: " << nodeNumInK<< endl; 
 990     int nodeNumInK2 = GetNodeNumInLayerKByLayerPrint(Tree, k);
 991     cout << "根据层序遍历,求得第" << k << "层节点数: " << nodeNumInK2<< endl; 
 992 
 993 
 994     //判断两个树结构是否相同:
 995     cout << "判断两个树结构是否形同: " << StructureCmp(Tree, Tree2) << endl;
 996 
 997     //判断B是否是A的子结构:
 998     bool hasSubtree = HasSubtree(Tree, Tree4);
 999     cout << "是否是子结构"  << hasSubtree << endl;
1000 
1001     //判断树是否是AVL树:
1002     int height = 0;
1003     bool isAvl = IsAVL(Tree, height);
1004     cout << "是否是AVL树: " << isAvl << endl;
1005 
1006     //二叉树的镜像:
1007     TreeMirror(Tree);
1008     cout << "镜像层序输出:";
1009     LayerOrderPrint(Tree);
1010     //恢复原状:
1011     TreeMirror(Tree);
1012     cout << endl;
1013 
1014     //由先序及中序遍历重建二叉树
1015     int length = nodeNum;
1016     int perOrder[] = {1,2,4,8,10,11,9,5,3,6,7};
1017     int inOrder[] = {10,8,11,4,9,2,5,1,6,3,7};
1018     BinaryTree rebuildTree = RebuildTree(perOrder, inOrder, length);
1019     cout << "重建后层序输出: ";
1020     LayerOrderPrint(rebuildTree);
1021     cout << endl;
1022 
1023     //寻找最低公共祖先节点
1024     PtrNode commonParentNode = GetLastCommonParent(Tree, Tree->pLeft->pLeft->pLeft, Tree->pRight->pRight);
1025     cout << commonParentNode->data << endl;
1026     commonParentNode = GetLastCommonParent(Tree, Tree->pLeft->pLeft->pLeft, Tree->pLeft->pRight);
1027     cout << "LCA: " << commonParentNode->data << endl;
1028     //非递归方法求公共祖先节点:
1029     commonParentNode = GetLastCommonParentNoRecur(Tree, Tree->pLeft->pLeft->pLeft, Tree->pLeft->pRight);
1030     cout << "LCA: " << commonParentNode->data << endl;
1031     //非递归方法求公共祖先节点:
1032     //递归方法二:
1033     commonParentNode = GetLCA(Tree, Tree->pLeft->pLeft->pLeft, Tree->pLeft->pRight);
1034     cout << "LCA: " << commonParentNode->data << endl;
1035     
1036 
1037     //二叉树节点之间的最大距离
1038     int nMaxLeft = 0;
1039     int nMaxRight = 0;
1040     int nMaxLen = GetLargestDestInNode(Tree, nMaxLeft, nMaxRight);
1041     cout << nMaxLen << endl;
1042 
1043 
1044     //和为某一个值得路径
1045     int expectedSum = 22;
1046     BinaryTree Tree3 = CreateBinaryTree3();
1047     GetRoad(Tree3, expectedSum);
1048 
1049     //判断二叉树是否是完全二叉树
1050     bool isCompleteTree = IsCompleteBinaryTree(Tree);
1051     cout << "是否是完全二叉树: " << isCompleteTree << endl;
1052 
1053 
1054     return 0;
1055 }

 

posted on 2014-09-02 17:16  鹏翔天际  阅读(249)  评论(0编辑  收藏  举报