二叉树精选

题目:输入两棵二叉树A和B,判断树B是不是A的子结构
递归判断:如果当前结点值相等,就判断左子树和右子树是否是子结构

  1. bool IsChildTree(Node * father, Node * son)  
  2. {  
  3.     if(father == NULL && son == NULL)  
  4.         return true;  
  5.   
  6.     if(father == NULL && son != NULL)  
  7.         return false;  
  8.   
  9.     if(father != NULL && son == NULL)  
  10.         return true;  
  11.   
  12.     if(father->data == son->data )  
  13.     {  
  14.          return IsChildTree(father->left, son->left) && IsChildTree(father->right, son->right);  
  15.     }  
  16.   
  17.     if(IsChildTree(father->left, son))  
  18.         return true;  
  19.   
  20.     if(IsChildTree(father->right, son))  
  21.         return true;  
  22.   
  23.     return false;  
  24. }  

 

题目:求二叉树中相距最远的两个节点之间的距离
求两节点的最远距离,实际就是求二叉树的直径。本问题可以转化为求“二叉树每个节点的左右子树高度和的最大值”。

  1. int TreeHeight(Node* root, int& max_distance)  
  2. {  
  3.     if(root == NULL)  
  4.     {  
  5.         max_distance = 0;  
  6.         return 0;  
  7.     }  
  8.   
  9.     int left_height,right_height;  
  10.   
  11.     if(root->left)  
  12.         left_height = TreeHeight(root->left,max_distance)+1;  
  13.     else  
  14.         left_height = 0;  
  15.   
  16.     if(root->right)  
  17.         right_height = TreeHeight(root->right,max_distance)+1;  
  18.     else  
  19.         right_height = 0;  
  20.   
  21.     int distance = left_height + right_height;  
  22.     if (max_distance < distance) max_distance = distance;  
  23.   
  24.     return (left_height > right_height ? left_height : right_height);  
  25. }  
  26.   
  27. int TreeDiameter(Node* root)  
  28. {  
  29.     int max_distance = 0;  
  30.     if(root) TreeHeight(root, max_distance);  
  31.     return max_distance;  
  32. }  

 

题目:求二叉树中节点的最大距离:如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,定义“距离”为两节点之间边的个数。

  1. //结点的定义  
  2. typedef struct Node  
  3. {  
  4.      Node * left;  
  5.      Node * right;  
  6.      int maxLeft;  
  7.      int maxRight;  
  8.      char chValue;  
  9. }Node,*pNode;  
  10.   
  11. //最大距离  
  12. int maxLen = 0;  
  13.   
  14. //寻找二叉树中节点的最大距离  
  15. void findMaxLength(Node* root)  
  16. {  
  17.      if(root == NULL) return;  
  18.   
  19.      //如果左子树为空,则该节点左边最长距离为0   
  20.      if(root->left == NULL)     root->maxLeft = 0;  
  21.   
  22.      //如果右子树为空,则该节点右边最长距离为0   
  23.      if(root->right == NULL)    root->maxRight = 0;  
  24.   
  25.      //如果左子树不为空,递归寻找左边最长距离   
  26.      if(root->left != NULL)     findMaxLength(root->left);  
  27.   
  28.      //如果右子树不为空,递归寻找右边最长距离   
  29.      if(root->right != NULL)    findMaxLength(root->right);  
  30.   
  31.      //计算左子树最长节点距离   
  32.      if(root->left != NULL)   
  33.      {  
  34.          int tempMax = 0;  
  35.          if(root->left->maxLeft > root->left->maxRight)  
  36.            tempMax = root->left->maxLeft;  
  37.          else tempMax = root->left->maxRight;  
  38.          root->maxLeft = tempMax+1;  
  39.      }  
  40.   
  41.      //计算右子树最长节点距离   
  42.      if(root->right != NULL)   
  43.      {  
  44.          int tempMax = 0;  
  45.          if(root->right->maxLeft > root->right->maxRight)  
  46.            tempMax = root->right->maxLeft;  
  47.          else tempMax = root->right->maxRight;  
  48.          root->maxRight = tempMax+1;  
  49.      }  
  50.   
  51.      //更新最长距离   
  52.      if(root->maxLeft+root->maxRight > maxLen)  
  53.        maxLen = root->maxLeft+root->maxRight;  
  54. }  


题目:重建二叉树:通过先序遍历和中序遍历的序列重建二叉树

  1. //通过先序遍历和中序遍历的序列重建二叉树  
  2. void ReBuild(char* pPreOrder,char* pInOrder,int nTreeLen,Node** pRoot)  
  3. {  
  4.      //检查边界条件   
  5.      if(pPreOrder == NULL || pInOrder == NULL)  
  6.         return ;  
  7.   
  8.      //获得前序遍历的第一个节点   
  9.      Node* temp = new Node;  
  10.      temp->data = *pPreOrder;  
  11.      temp->left = NULL;  
  12.      temp->right = NULL;  
  13.   
  14.      //如果节点为空,把当前节点复制到根节点   
  15.      if(*pRoot == NULL) *pRoot = temp;  
  16.   
  17.      //如果当前树长为1,那么已经是最后一个节点   
  18.      if(nTreeLen == 1) return;  
  19.   
  20.      //寻找子树长度   
  21.      char* pOrgInOrder = pInOrder;  
  22.      char* pLeftEnd = pInOrder;  
  23.      int nTempLen = 0;  
  24.   
  25.      //找到左子树的结尾   
  26.      while(*pPreOrder != *pLeftEnd)  
  27.      {  
  28.        if(pPreOrder == NULL || pLeftEnd == NULL)  
  29.           return;  
  30.        //记录临时长度,以免溢出   
  31.        nTempLen++;  
  32.        if(nTempLen > nTreeLen) break;  
  33.        pLeftEnd++;  
  34.      }  
  35.   
  36.      //寻找左子树长度   
  37.      int nLeftLen = (int)(pLeftEnd-pOrgInOrder);  
  38.   
  39.      //寻找右子树长度   
  40.      int nRightLen = nTreeLen-nLeftLen-1;  
  41.   
  42.      //重建左子树   
  43.      if(nLeftLen > 0)  
  44.        ReBuild(pPreOrder+1,pInOrder,nLeftLen,&((*pRoot)->left));  
  45.   
  46.      //重建右子树   
  47.      if(nRightLen > 0)  
  48.        ReBuild(pPreOrder+nLeftLen+1,pInOrder+nLeftLen+1,nRightLen,&((*pRoot)->right));  
  49. }  

 

题目:寻找最近公共祖先LCA(Lowest Common Ancestor)

  1. Node* getLCA(Node* root,Node* x,Node* y)  
  2. {  
  3.     if(root == NULL) return NULL;  
  4.     if(x == root || y == root) return root;  
  5.     Node* pleft = getLCA(root->left,x,y);  
  6.     Node* pright = getLCA(root->right,x,y);  
  7.     if(pleft == NULL) return pright;  
  8.     else if(pright == NULL)return pleft;  
  9.     else return root;  
  10. }  

分别得到根节点root到结点x的路径和到结点y的路径,再比较路径中第一个相同的结点,即是LCA

  1. //得到根节点pHead到pNode的路径  
  2. bool GetNodePath(Node* pHead, Node* pNode, std::list<Node*>& path)  
  3. {  
  4.     if(pHead == pNode)  
  5.         return true;  
  6.   
  7.     path.push_back(pHead);  
  8.   
  9.     bool found = false;  
  10.   
  11.     if(pHead->left != NULL)  
  12.         found = GetNodePath(pHead->left, pNode, path);  
  13.   
  14.     if(!found && pHead->right)  
  15.         found = GetNodePath(pHead->right, pNode, path);  
  16.   
  17.     if(!found)  
  18.         path.pop_back();  
  19.   
  20.     return found;  
  21. }  

题目:寻找二叉搜索树(BST)的最低公共祖先(LCA)
利用BST的性质:从根结点开始搜索,当第一次遇到当前结点的值介于两个给定的结点值之间时,这个当前结点就是要找的LCA

  1. Node* FindLCA(Node* root,int x, int y)  
  2. {  
  3.     Node * t = root;  
  4.     while(1)  
  5.     {  
  6.         if(t->data > x && t->data > y)  
  7.             t = t->left;  
  8.         else if(t->data < x && t->data < y)  
  9.             t = t->right;  
  10.         else return t;  
  11.     }  
  12. }  

 

题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果,因此返回true。
         8
       /    \
      6     10
     / \       /  \
    5  7  9    11
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。
分析:这是一道trilogy的笔试题,主要考查对二元查找树的理解。
在后续遍历得到的序列中,最后一个元素为树的根结点。从头开始扫描这个序列,比根结点小的元素都应该位于序列的左半部分;从第一个大于根节点开始到根结点前面的一个元素为止,所有元素都应该大于根结点,因为这部分元素对应的是树的右子树。根据这样的划分,把序列划分为左右两部分,我们递归地确认序列的左、右两部分是不是都是二元查找树。
参考代码:

  1. ///  
  2. // Verify whether a squence of integers are the post order traversal  
  3. // of a binary search tree (BST)  
  4. // Input: squence - the squence of integers  
  5. //        length  - the length of squence  
  6. // Return: return ture if the squence is traversal result of a BST,  
  7. //         otherwise, return false  
  8. ///  
  9. bool verifySquenceOfBST(int squence[], int length)  
  10. {  
  11.       if(squence == NULL || length <= 0)  
  12.             return false;  
  13.   
  14.       // root of a BST is at the end of post order traversal squence  
  15.       int root = squence[length - 1];  
  16.   
  17.       // the nodes in left sub-tree are less than the root  
  18.       int i = 0;  
  19.       for(; i < length - 1; ++ i)  
  20.       {  
  21.             if(squence[i] > root)  
  22.                   break;  
  23.       }  
  24.   
  25.       // the nodes in the right sub-tree are greater than the root  
  26.       int j = i;  
  27.       for(; j < length - 1; ++ j)  
  28.       {  
  29.             if(squence[j] < root)  
  30.                   return false;  
  31.       }  
  32.   
  33.       // verify whether the left sub-tree is a BST  
  34.       bool left = true;  
  35.       if(i > 0)  
  36.             left = verifySquenceOfBST(squence, i);  
  37.   
  38.       // verify whether the right sub-tree is a BST  
  39.       bool right = true;  
  40.       if(i < length - 1)  
  41.             right = verifySquenceOfBST(squence + i, length - i - 1);  
  42.   
  43.       return (left && right);  
  44. }  

 

题目:怎样编写一个程序,把一个有序整数数组放到二叉搜索树中?
分析:本题考察二叉搜索树的建树方法,简单的递归结构。关于树的算法设计一定要联想到递归,因为树本身就是递归的定义。

参考代码:

  1. Node* array_to_tree(int array[],int start,int end)  
  2. {  
  3.     if (start > end) return NULL;  
  4.     int m = start+(end-start)/2;  
  5.     Node* root = new Node(array[m]);  
  6.     root->left = array_to_tree(array,start,m-1);  
  7.     root->right = array_to_tree(array,m+1,end);  
  8.     return root;  
  9. }  
  10.   
  11. Node* array2Tree(int array[],int n)  
  12. {  
  13.     return array_to_tree(array,0,n-1);  
  14. }  

 

题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。
比如将二元查找树
                                           10
                                          /    \
                                        6       14
                                      /  \        /    \
                                   4     8  12    16
转换成双向链表 4=6=8=10=12=14=16。

分析:本题是微软的面试题。很多与树相关的题目都是用递归的思路来解决,本题也不例外。下面我们用两种不同的递归思路来分析。

  思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最后链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)。从树的根结点开始递归调整所有结点。

  思路二:我们可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。

参考代码:

  1. //定义二元查找树结点的数据结构如下:  
  2.     struct BSTreeNode // a node in the binary search tree  
  3.     {  
  4.         int        m_nValue; // value of node  
  5.         BSTreeNode *m_pLeft; // left child of node  
  6.         BSTreeNode *m_pRight; // right child of node  
  7.     };  
  8.   
  9. //思路一对应的代码:  
  10. ///  
  11. // Covert a sub binary-search-tree into a sorted double-linked list  
  12. // Input: pNode - the head of the sub tree  
  13. //        asRight - whether pNode is the right child of its parent  
  14. // Output: if asRight is true, return the least node in the sub-tree  
  15. //         else return the greatest node in the sub-tree  
  16. ///  
  17. BSTreeNode* ConvertNode(BSTreeNode* pNode, bool asRight)  
  18. {  
  19.       if(!pNode)  
  20.             return NULL;  
  21.   
  22.       BSTreeNode *pLeft = NULL;  
  23.       BSTreeNode *pRight = NULL;  
  24.   
  25.       // Convert the left sub-tree  
  26.       if(pNode->m_pLeft)  
  27.             pLeft = ConvertNode(pNode->m_pLeft, false);  
  28.   
  29.       // Connect the greatest node in the left sub-tree to the current node  
  30.       if(pLeft)  
  31.       {  
  32.             pLeft->m_pRight = pNode;  
  33.             pNode->m_pLeft = pLeft;  
  34.       }  
  35.   
  36.       // Convert the right sub-tree  
  37.       if(pNode->m_pRight)  
  38.             pRight = ConvertNode(pNode->m_pRight, true);  
  39.   
  40.       // Connect the least node in the right sub-tree to the current node  
  41.       if(pRight)  
  42.       {  
  43.             pNode->m_pRight = pRight;  
  44.             pRight->m_pLeft = pNode;  
  45.       }  
  46.   
  47.       BSTreeNode *pTemp = pNode;  
  48.   
  49.       // If the current node is the right child of its parent,   
  50.       // return the least node in the tree whose root is the current node  
  51.       if(asRight)  
  52.       {  
  53.             while(pTemp->m_pLeft)  
  54.                   pTemp = pTemp->m_pLeft;  
  55.       }  
  56.       // If the current node is the left child of its parent,   
  57.       // return the greatest node in the tree whose root is the current node  
  58.       else  
  59.       {  
  60.             while(pTemp->m_pRight)  
  61.                   pTemp = pTemp->m_pRight;  
  62.       }  
  63.    
  64.       return pTemp;  
  65. }  
  66.   
  67. ///  
  68. // Covert a binary search tree into a sorted double-linked list  
  69. // Input: the head of tree  
  70. // Output: the head of sorted double-linked list  
  71. ///  
  72. BSTreeNode* Convert(BSTreeNode* pHeadOfTree)  
  73. {  
  74.       // As we want to return the head of the sorted double-linked list,  
  75.       // we set the second parameter to be true  
  76.       return ConvertNode(pHeadOfTree, true);  
  77. }  
  78.   
  79. //思路二对应的代码:  
  80. ///  
  81. // Covert a sub binary-search-tree into a sorted double-linked list  
  82. // Input: pNode - the head of the sub tree  
  83. //       pLastNodeInList - the tail of the double-linked list  
  84. ///  
  85. void ConvertNode(BSTreeNode* pNode, BSTreeNode*& pLastNodeInList)  
  86. {  
  87.       if(pNode == NULL)  
  88.             return;  
  89.   
  90.       BSTreeNode *pCurrent = pNode;  
  91.   
  92.       // Convert the left sub-tree  
  93.       if (pCurrent->m_pLeft != NULL)  
  94.             ConvertNode(pCurrent->m_pLeft, pLastNodeInList);  
  95.   
  96.       // Put the current node into the double-linked list  
  97.       pCurrent->m_pLeft = pLastNodeInList;   
  98.       if(pLastNodeInList != NULL)  
  99.             pLastNodeInList->m_pRight = pCurrent;  
  100.   
  101.       pLastNodeInList = pCurrent;  
  102.   
  103.       // Convert the right sub-tree  
  104.       if (pCurrent->m_pRight != NULL)  
  105.             ConvertNode(pCurrent->m_pRight, pLastNodeInList);  
  106. }  
  107.   
  108. ///  
  109. // Covert a binary search tree into a sorted double-linked list  
  110. // Input: pHeadOfTree - the head of tree  
  111. // Output: the head of sorted double-linked list  
  112. ///  
  113. BSTreeNode* Convert_Solution1(BSTreeNode* pHeadOfTree)  
  114. {  
  115.       BSTreeNode *pLastNodeInList = NULL;  
  116.       ConvertNode(pHeadOfTree, pLastNodeInList);  
  117.   
  118.       // Get the head of the double-linked list  
  119.       BSTreeNode *pHeadOfList = pLastNodeInList;  
  120.       while(pHeadOfList && pHeadOfList->m_pLeft)  
  121.             pHeadOfList = pHeadOfList->m_pLeft;  
  122.   
  123.       return pHeadOfList;  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值