1. 程式人生 > >二叉樹筆試題

二叉樹筆試題

題目:輸入兩棵二叉樹A和B,判斷樹B是不是A的子結構

先判斷兩棵二叉樹任一都不為NULL
遞迴判斷:如果當前結點值相等,就判斷左子樹和右子樹是否是子結構

[cpp] view plain copy print?
  1. bool IsChildTree(Node * father, Node * son)  
  2. {  
  3.     if(father == NULL && son == NULL)  
  4.         return true;  
  5.     if(father == NULL && son != NULL)  
  6.         return false;  
  7.     if
    (father != NULL && son == NULL)  
  8.         return true;  
  9.     if(father->data == son->data )  
  10.     {  
  11.          return IsChildTree(father->left, son->left) && IsChildTree(father->right, son->right);  
  12.     }  
  13.     if(IsChildTree(father->left, son))  
  14.         return true;  
  15.     if(IsChildTree(father->right, son))  
  16.         return true;  
  17.     return false;  
  18. }  
bool IsChildTree(Node * father, Node * son)
{
    if(father == NULL && son == NULL)
        return true;

    if(father == NULL && son != NULL)
        return false;

    if(father != NULL && son == NULL)
        return true;

    if(father->data == son->data )
    {
         return IsChildTree(father->left, son->left) && IsChildTree(father->right, son->right);
    }

    if(IsChildTree(father->left, son))
        return true;

    if(IsChildTree(father->right, son))
        return true;

    return false;
}

題目:求二叉樹中相距最遠的兩個節點之間的距離


求兩節點的最遠距離,實際就是求二叉樹的直徑。本問題可以轉化為求“二叉樹每個節點的左右子樹高度和的最大值”。

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

    int left_height,right_height;

    if(root->left)
        left_height = TreeHeight(root->left,max_distance)+1;
    else
        left_height = 0;

    if(root->right)
        right_height = TreeHeight(root->right,max_distance)+1;
    else
        right_height = 0;

    int distance = left_height + right_height;
    if (max_distance < distance) max_distance = distance;

    return (left_height > right_height ? left_height : right_height);
}

int TreeDiameter(Node* root)
{
    int max_distance = 0;
    if(root) TreeHeight(root, max_distance);
    return max_distance;
}

題目:求二叉樹中節點的最大距離:如果我們把二叉樹看成一個圖,父子節點之間的連線看成是雙向的,定義“距離”為兩節點之間邊的個數。

[cpp] view plain copy print?
  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. int maxLen = 0;  
  12. //尋找二叉樹中節點的最大距離  
  13. void findMaxLength(Node* root)  
  14. {  
  15.      if(root == NULL) return;  
  16.      //如果左子樹為空,則該節點左邊最長距離為0   
  17.      if(root->left == NULL)     root->maxLeft = 0;  
  18.      //如果右子樹為空,則該節點右邊最長距離為0   
  19.      if(root->right == NULL)    root->maxRight = 0;  
  20.      //如果左子樹不為空,遞迴尋找左邊最長距離   
  21.      if(root->left != NULL)     findMaxLength(root->left);  
  22.      //如果右子樹不為空,遞迴尋找右邊最長距離   
  23.      if(root->right != NULL)    findMaxLength(root->right);  
  24.      //計算左子樹最長節點距離   
  25.      if(root->left != NULL)   
  26.      {  
  27.          int tempMax = 0;  
  28.          if(root->left->maxLeft > root->left->maxRight)  
  29.            tempMax = root->left->maxLeft;  
  30.          else tempMax = root->left->maxRight;  
  31.          root->maxLeft = tempMax+1;  
  32.      }  
  33.      //計算右子樹最長節點距離   
  34.      if(root->right != NULL)   
  35.      {  
  36.          int tempMax = 0;  
  37.          if(root->right->maxLeft > root->right->maxRight)  
  38.            tempMax = root->right->maxLeft;  
  39.          else tempMax = root->right->maxRight;  
  40.          root->maxRight = tempMax+1;  
  41.      }  
  42.      //更新最長距離   
  43.      if(root->maxLeft+root->maxRight > maxLen)  
  44.        maxLen = root->maxLeft+root->maxRight;  
  45. }  
//結點的定義
typedef struct Node
{
     Node * left;
     Node * right;
     int maxLeft;
     int maxRight;
     char chValue;
}Node,*pNode;

//最大距離
int maxLen = 0;

//尋找二叉樹中節點的最大距離
void findMaxLength(Node* root)
{
     if(root == NULL) return;

     //如果左子樹為空,則該節點左邊最長距離為0 
     if(root->left == NULL)     root->maxLeft = 0;

     //如果右子樹為空,則該節點右邊最長距離為0 
     if(root->right == NULL)    root->maxRight = 0;

     //如果左子樹不為空,遞迴尋找左邊最長距離 
     if(root->left != NULL)     findMaxLength(root->left);

     //如果右子樹不為空,遞迴尋找右邊最長距離 
     if(root->right != NULL)    findMaxLength(root->right);

     //計算左子樹最長節點距離 
     if(root->left != NULL) 
     {
         int tempMax = 0;
         if(root->left->maxLeft > root->left->maxRight)
           tempMax = root->left->maxLeft;
         else tempMax = root->left->maxRight;
         root->maxLeft = tempMax+1;
     }

     //計算右子樹最長節點距離 
     if(root->right != NULL) 
     {
         int tempMax = 0;
         if(root->right->maxLeft > root->right->maxRight)
           tempMax = root->right->maxLeft;
         else tempMax = root->right->maxRight;
         root->maxRight = tempMax+1;
     }

     //更新最長距離 
     if(root->maxLeft+root->maxRight > maxLen)
       maxLen = root->maxLeft+root->maxRight;
}


題目:重建二叉樹:通過先序遍歷和中序遍歷的序列重建二叉樹

[cpp] view plain copy print?
  1. //通過先序遍歷和中序遍歷的序列重建二叉樹  
  2. void ReBuild(char* pPreOrder,char* pInOrder,int nTreeLen,Node** pRoot)  
  3. {  
  4.      //檢查邊界條件   
  5.      if(pPreOrder == NULL || pInOrder == NULL)  
  6.         return ;  
  7.      //獲得前序遍歷的第一個節點   
  8.      Node* temp = new Node;  
  9.      temp->data = *pPreOrder;  
  10.      temp->left = NULL;  
  11.      temp->right = NULL;  
  12.      //如果節點為空,把當前節點複製到根節點   
  13.      if(*pRoot == NULL) *pRoot = temp;  
  14.      //如果當前樹長為1,那麼已經是最後一個節點   
  15.      if(nTreeLen == 1) return;  
  16.      //尋找子樹長度   
  17.      char* pOrgInOrder = pInOrder;  
  18.      char* pLeftEnd = pInOrder;  
  19.      int nTempLen = 0;  
  20.      //找到左子樹的結尾   
  21.      while(*pPreOrder != *pLeftEnd)  
  22.      {  
  23.        if(pPreOrder == NULL || pLeftEnd == NULL)  
  24.           return;  
  25.        //記錄臨時長度,以免溢位   
  26.        nTempLen++;  
  27.        if(nTempLen > nTreeLen) break;  
  28.        pLeftEnd++;  
  29.      }  
  30.      //尋找左子樹長度   
  31.      int nLeftLen = (int)(pLeftEnd-pOrgInOrder);  
  32.      //尋找右子樹長度   
  33.      int nRightLen = nTreeLen-nLeftLen-1;  
  34.      //重建左子樹   
  35.      if(nLeftLen > 0)  
  36.        ReBuild(pPreOrder+1,pInOrder,nLeftLen,&((*pRoot)->left));  
  37.      //重建右子樹   
  38.      if(nRightLen > 0)  
  39.        ReBuild(pPreOrder+nLeftLen+1,pInOrder+nLeftLen+1,nRightLen,&((*pRoot)->right));  
  40. }  
//通過先序遍歷和中序遍歷的序列重建二叉樹
void ReBuild(char* pPreOrder,char* pInOrder,int nTreeLen,Node** pRoot)
{
     //檢查邊界條件 
     if(pPreOrder == NULL || pInOrder == NULL)
        return ;

     //獲得前序遍歷的第一個節點 
     Node* temp = new Node;
     temp->data = *pPreOrder;
     temp->left = NULL;
     temp->right = NULL;

     //如果節點為空,把當前節點複製到根節點 
     if(*pRoot == NULL) *pRoot = temp;

     //如果當前樹長為1,那麼已經是最後一個節點 
     if(nTreeLen == 1) return;

     //尋找子樹長度 
     char* pOrgInOrder = pInOrder;
     char* pLeftEnd = pInOrder;
     int nTempLen = 0;

     //找到左子樹的結尾 
     while(*pPreOrder != *pLeftEnd)
     {
       if(pPreOrder == NULL || pLeftEnd == NULL)
          return;
       //記錄臨時長度,以免溢位 
       nTempLen++;
       if(nTempLen > nTreeLen) break;
       pLeftEnd++;
     }

     //尋找左子樹長度 
     int nLeftLen = (int)(pLeftEnd-pOrgInOrder);

     //尋找右子樹長度 
     int nRightLen = nTreeLen-nLeftLen-1;

     //重建左子樹 
     if(nLeftLen > 0)
       ReBuild(pPreOrder+1,pInOrder,nLeftLen,&((*pRoot)->left));

     //重建右子樹 
     if(nRightLen > 0)
       ReBuild(pPreOrder+nLeftLen+1,pInOrder+nLeftLen+1,nRightLen,&((*pRoot)->right));
}

題目:尋找最近公共祖先LCA(Lowest Common Ancestor)

[cpp] view plain copy print?
  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. }  
Node* getLCA(Node* root,Node* x,Node* y)
{
    if(root == NULL) return NULL;
    if(x == root || y == root) return root;
    Node* pleft = getLCA(root->left,x,y);
    Node* pright = getLCA(root->right,x,y);
    if(pleft == NULL) return pright;
    else if(pright == NULL)return pleft;
    else return root;
}

分別得到根節點root到結點x的路徑和到結點y的路徑,再比較路徑中第一個相同的結點,即是LCA

[cpp] view plain copy print?
  1. //得到根節點pHead到pNode的路徑  
  2. bool GetNodePath(Node* pHead, Node* pNode, std::list<Node*>& path)  
  3. {  
  4.     if(pHead == pNode)  
  5.         return true;  
  6.     path.push_back(pHead);  
  7.     bool found = false;  
  8.     if(pHead->left != NULL)  
  9.         found = GetNodePath(pHead->left, pNode, path);  
  10.     if(!found && pHead->right)  
  11.         found = GetNodePath(pHead->right, pNode, path);  
  12.     if(!found)  
  13.         path.pop_back();  
  14.     return found;  
  15. }  
//得到根節點pHead到pNode的路徑
bool GetNodePath(Node* pHead, Node* pNode, std::list<Node*>& path)
{
    if(pHead == pNode)
        return true;

    path.push_back(pHead);

    bool found = false;

    if(pHead->left != NULL)
        found = GetNodePath(pHead->left, pNode, path);

    if(!found && pHead->right)
        found = GetNodePath(pHead->right, pNode, path);

    if(!found)
        path.pop_back();

    return found;
}

題目:尋找二叉搜尋樹(BST)的最低公共祖先(LCA)
利用BST的性質:從根結點開始搜尋,當第一次遇到當前結點的值介於兩個給定的結點值之間時,這個當前結點就是要找的LCA

[cpp] view plain copy print?
  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. }  
Node* FindLCA(Node* root,int x, int y)
{
    Node * t = root;
    while(1)
    {
        if(t->data > x && t->data > y)
            t = t->left;
        else if(t->data < x && t->data < y)
            t = t->right;
        else return t;
    }
}

題目:輸入一個整數陣列,判斷該陣列是不是某二元查詢樹的後序遍歷的結果。如果是返回true,否則返回false。
例如輸入5、7、6、9、11、10、8,由於這一整數序列是如下樹的後序遍歷結果,因此返回true。
         8
       /    \
      6     10
     / \       /  \
    5  7  9    11
如果輸入7、4、6、5,沒有哪棵樹的後序遍歷的結果是這個序列,因此返回false。
分析:這是一道trilogy的筆試題,主要考查對二元查詢樹的理解。
在後續遍歷得到的序列中,最後一個元素為樹的根結點。從頭開始掃描這個序列,比根結點小的元素都應該位於序列的左半部分;從第一個大於根節點開始到根結點前面的一個元素為止,所有元素都應該大於根結點,因為這部分元素對應的是樹的右子樹。根據這樣的劃分,把序列劃分為左右兩部分,我們遞迴地確認序列的左、右兩部分是不是都是二元查詢樹。
參考程式碼:

[cpp] view plain copy print?
  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.       // root of a BST is at the end of post order traversal squence  
  14.       int root = squence[length - 1];  
  15.       // the nodes in left sub-tree are less than the root  
  16.       int i = 0;  
  17.       for(; i < length - 1; ++ i)  
  18.       {  
  19.             if(squence[i] > root)  
  20.                   break;  
  21.       }  
  22.       // the nodes in the right sub-tree are greater than the root  
  23.       int j = i;  
  24.       for(; j < length - 1; ++ j)  
  25.       {  
  26.             if(squence[j] < root)  
  27.                   return false;  
  28.       }  
  29.       // verify whether the left sub-tree is a BST  
  30.       bool left = true;  
  31.       if(i > 0)  
  32.             left = verifySquenceOfBST(squence, i);  
  33.       // verify whether the right sub-tree is a BST  
  34.       bool right = true;  
  35.       if(i < length - 1)  
  36.             right = verifySquenceOfBST(squence + i, length - i - 1);  
  37.       return (left && right);  
  38. }  
///////////////////////////////////////////////////////////////////////
// Verify whether a squence of integers are the post order traversal
// of a binary search tree (BST)
// Input: squence - the squence of integers
//        length  - the length of squence
// Return: return ture if the squence is traversal result of a BST,
//         otherwise, return false
///////////////////////////////////////////////////////////////////////
bool verifySquenceOfBST(int squence[], int length)
{
      if(squence == NULL || length <= 0)
            return false;

      // root of a BST is at the end of post order traversal squence
      int root = squence[length - 1];

      // the nodes in left sub-tree are less than the root
      int i = 0;
      for(; i < length - 1; ++ i)
      {
            if(squence[i] > root)
                  break;
      }

      // the nodes in the right sub-tree are greater than the root
      int j = i;
      for(; j < length - 1; ++ j)
      {
            if(squence[j] < root)
                  return false;
      }

      // verify whether the left sub-tree is a BST
      bool left = true;
      if(i > 0)
            left = verifySquenceOfBST(squence, i);

      // verify whether the right sub-tree is a BST
      bool right = true;
      if(i < length - 1)
            right = verifySquenceOfBST(squence + i, length - i - 1);

      return (left && right);
}

題目:怎樣編寫一個程式,把一個有序整數陣列放到二叉搜尋樹中?
分析:本題考察二叉搜尋樹的建樹方法,簡單的遞迴結構。關於樹的演算法設計一定要聯想到遞迴,因為樹本身就是遞迴的定義。

參考程式碼:

[cpp] view plain copy print?
  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. Node* array2Tree(int array[],int n)  
  11. {  
  12.     return array_to_tree(array,0,n-1);  
  13. }  
Node* array_to_tree(int array[],int start,int end)
{
    if (start > end) return NULL;
    int m = start+(end-start)/2;
    Node* root = new Node(array[m]);
    root->left = array_to_tree(array,start,m-1);
    root->right = array_to_tree(array,m+1,end);
    return root;
}

Node* array2Tree(int array[],int n)
{
    return array_to_tree(array,0,n-1);
}

題目:輸入一棵二元查詢樹,將該二元查詢樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只調整指標的指向。
比如將二元查詢樹
                                           10
                                          /    \
                                        6       14
                                      /  \        /    \
                                   4     8  12    16
轉換成雙向連結串列 4=6=8=10=12=14=16。

分析:本題是微軟的面試題。很多與樹相關的題目都是用遞迴的思路來解決,本題也不例外。下面我們用兩種不同的遞迴思路來分析。

  思路一:當我們到達某一結點準備調整以該結點為根結點的子樹時,先調整其左子樹將左子樹轉換成一個排好序的左子連結串列,再調整其右子樹轉換右子連結串列。最後連結左子連結串列的最右結點(左子樹的最大結點)、當前結點和右子連結串列的最左結點(右子樹的最小結點)。從樹的根結點開始遞迴調整所有結點。

  思路二:我們可以中序遍歷整棵樹。按照這個方式遍歷樹,比較小的結點先訪問。如果我們每訪問一個結點,假設之前訪問過的結點已經調整成一個排序雙向連結串列,我們再把調整當前結點的指標將其連結到連結串列的末尾。當所有結點都訪問過之後,整棵樹也就轉換成一個排序雙向連結串列了。

參考程式碼:

[cpp] view plain copy print?
  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. // Covert a sub binary-search-tree into a sorted double-linked list  
  11. // Input: pNode - the head of the sub tree  
  12. //        asRight - whether pNode is the right child of its parent  
  13. // Output: if asRight is true, return the least node in the sub-tree  
  14. //         else return the greatest node in the sub-tree  
  15. ///////////////////////////////////////////////////////////////////////  
  16. BSTreeNode* ConvertNode(BSTreeNode* pNode, bool asRight)  
  17. {  
  18.       if(!pNode)  
  19.             return NULL;  
  20.       BSTreeNode *pLeft = NULL;  
  21.       BSTreeNode *pRight = NULL;  
  22.       // Convert the left sub-tree  
  23.       if(pNode->m_pLeft)  
  24.             pLeft = ConvertNode(pNode->m_pLeft, false);  
  25.       // Connect the greatest node in the left sub-tree to the current node  
  26.       if(pLeft)  
  27.       {  
  28.             pLeft->m_pRight = pNode;  
  29.             pNode->m_pLeft = pLeft;  
  30.       }  
  31.       // Convert the right sub-tree  
  32.       if(pNode->m_pRight)  
  33.             pRight = ConvertNode(pNode->m_pRight, true);  
  34.       // Connect the least node in the right sub-tree to the current node  
  35.       if(pRight)  
  36.       {  
  37.             pNode->m_pRight = pRight;  
  38.             pRight->m_pLeft = pNode;  
  39.       }  
  40.       BSTreeNode *pTemp = pNode;  
  41.       // If the current node is the right child of its parent,   
  42.       // return the least node in the tree whose root is the current node  
  43.       if(asRight)  
  44.       {  
  45.             while(pTemp->m_pLeft)  
  46.                   pTemp = pTemp->m_pLeft;  
  47.       }  
  48.       // If the current node is the left child of its parent,   
  49.       // return the greatest node in the tree whose root is the current node  
  50.       else  
  51.       {  
  52.             while(pTemp->m_pRight)  
  53.                   pTemp = pTemp->m_pRight;  
  54.       }  
  55.       return pTemp;  
  56. }  
  57. ///////////////////////////////////////////////////////////////////////  
  58. // Covert a binary search tree into a sorted double-linked list  
  59. // Input: the head of tree  
  60. // Output: the head of sorted double-linked list  
  61. ///////////////////////////////////////////////////////////////////////  
  62. BSTreeNode* Convert(BSTreeNode* pHeadOfTree)  
  63. {  
  64.       // As we want to return the head of the sorted double-linked list,  
  65.       // we set the second parameter to be true  
  66.       return ConvertNode(pHeadOfTree, true);  
  67. }  
  68. //思路二對應的程式碼:  
  69. ///////////////////////////////////////////////////////////////////////  
  70. // Covert a sub binary-search-tree into a sorted double-linked list  
  71. // Input: pNode - the head of the sub tree  
  72. //       pLastNodeInList - the tail of the double-linked list  
  73. ///////////////////////////////////////////////////////////////////////  
  74. void ConvertNode(BSTreeNode* pNode, BSTreeNode*& pLastNodeInList)  
  75. {  
  76.       if(pNode == NULL)  
  77.             return;  
  78.       BSTreeNode *pCurrent = pNode;  
  79.       // Convert the left sub-tree  
  80.       if (pCurrent->m_pLeft != NULL)  
  81.             ConvertNode(pCurrent->m_pLeft, pLastNodeInList);  
  82.       // Put the current node into the double-linked list  
  83.       pCurrent->m_pLeft = pLastNodeInList;   
  84.       if(pLastNodeInList != NULL)  
  85.             pLastNodeInList->m_pRight = pCurrent;  
  86.       pLastNodeInList = pCurrent;  
  87.       // Convert the right sub-tree  
  88.       if (pCurrent->m_pRight != NULL)  
  89.             ConvertNode(pCurrent->m_pRight, pLastNodeInList);  
  90. }  
  91. ///////////////////////////////////////////////////////////////////////  
  92. // Covert a binary search tree into a sorted double-linked list  
  93. // Input: pHeadOfTree - the head of tree  
  94. // Output: the head of sorted double-linked list  
  95. ///////////////////////////////////////////////////////////////////////  
  96. BSTreeNode* Convert_Solution1(BSTreeNode* pHeadOfTree)  
  97. {  
  98.       BSTreeNode *pLastNodeInList = NULL;  
  99.       ConvertNode(pHeadOfTree, pLastNodeInList);  
  100.       // Get the head of the double-linked list  
  101.       BSTreeNode *pHeadOfList = pLastNodeInList;  
  102.       while(pHeadOfList && pHeadOfList->m_pLeft)  
  103.             pHeadOfList = pHeadOfList->m_pLeft;  
  104.       return pHeadOfList;  
  105. }  
//定義二元查詢樹結點的資料結構如下:
    struct BSTreeNode // a node in the binary search tree
    {
        int        m_nValue; // value of node
        BSTreeNode *m_pLeft; // left child of node
        BSTreeNode *m_pRight; // right child of node
    };

//思路一對應的程式碼:
///////////////////////////////////////////////////////////////////////
// Covert a sub binary-search-tree into a sorted double-linked list
// Input: pNode - the head of the sub tree
//        asRight - whether pNode is the right child of its parent
// Output: if asRight is true, return the least node in the sub-tree
//         else return the greatest node in the sub-tree
///////////////////////////////////////////////////////////////////////
BSTreeNode* ConvertNode(BSTreeNode* pNode, bool asRight)
{
      if(!pNode)
            return NULL;

      BSTreeNode *pLeft = NULL;
      BSTreeNode *pRight = NULL;

      // Convert the left sub-tree
      if(pNode->m_pLeft)
            pLeft = ConvertNode(pNode->m_pLeft, false);

      // Connect the greatest node in the left sub-tree to the current node
      if(pLeft)
      {
            pLeft->m_pRight = pNode;
            pNode->m_pLeft = pLeft;
      }

      // Convert the right sub-tree
      if(pNode->m_pRight)
            pRight = ConvertNode(pNode->m_pRight, true);

      // Connect the least node in the right sub-tree to the current node
      if(pRight)
      {
            pNode->m_pRight = pRight;
            pRight->m_pLeft = pNode;
      }

      BSTreeNode *pTemp = pNode;

      // If the current node is the right child of its parent, 
      // return the least node in the tree whose root is the current node
      if(asRight)
      {
            while(pTemp->m_pLeft)
                  pTemp = pTemp->m_pLeft;
      }
      // If the current node is the left child of its parent, 
      // return the greatest node in the tree whose root is the current node
      else
      {
            while(pTemp->m_pRight)
                  pTemp = pTemp->m_pRight;
      }
 
      return pTemp;
}

///////////////////////////////////////////////////////////////////////
// Covert a binary search tree into a sorted double-linked list
// Input: the head of tree
// Output: the head of sorted double-linked list
///////////////////////////////////////////////////////////////////////
BSTreeNode* Convert(BSTreeNode* pHeadOfTree)
{
      // As we want to return the head of the sorted double-linked list,
      // we set the second parameter to be true
      return ConvertNode(pHeadOfTree, true);
}

//思路二對應的程式碼:
///////////////////////////////////////////////////////////////////////
// Covert a sub binary-search-tree into a sorted double-linked list
// Input: pNode - the head of the sub tree
//       pLastNodeInList - the tail of the double-linked list
///////////////////////////////////////////////////////////////////////
void ConvertNode(BSTreeNode* pNode, BSTreeNode*& pLastNodeInList)
{
      if(pNode == NULL)
            return;

      BSTreeNode *pCurrent = pNode;

      // Convert the left sub-tree
      if (pCurrent->m_pLeft != NULL)
            ConvertNode(pCurrent->m_pLeft, pLastNodeInList);

      // Put the current node into the double-linked list
      pCurrent->m_pLeft = pLastNodeInList; 
      if(pLastNodeInList != NULL)
            pLastNodeInList->m_pRight = pCurrent;

      pLastNodeInList = pCurrent;

      // Convert the right sub-tree
      if (pCurrent->m_pRight != NULL)
            ConvertNode(pCurrent->m_pRight, pLastNodeInList);
}

///////////////////////////////////////////////////////////////////////
// Covert a binary search tree into a sorted double-linked list
// Input: pHeadOfTree - the head of tree
// Output: the head of sorted double-linked list
///////////////////////////////////////////////////////////////////////
BSTreeNode* Convert_Solution1(BSTreeNode* pHeadOfTree)
{
      BSTreeNode *pLastNodeInList = NULL;
      ConvertNode(pHeadOfTree, pLastNodeInList);

      // Get the head of the double-linked list
      BSTreeNode *pHeadOfList = pLastNodeInList;
      while(pHeadOfList && pHeadOfList->m_pLeft)
            pHeadOfList = pHeadOfList->m_pLeft;

      return pHeadOfList;
}

相關推薦

C++試題

else 子節點 typename data fad pub struct char s[] 前序遍歷 #include <iostream> #include <stack> #include <queue> usi

試題

題目:輸入兩棵二叉樹A和B,判斷樹B是不是A的子結構 先判斷兩棵二叉樹任一都不為NULL 遞迴判斷:如果當前結點值相等,就判斷左子樹和右子樹是否是子結構 [cpp] view plain copy print? bool IsChildTree(Node * father, Node * so

試題彙總

樹是一種比較重要的資料結構,尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之分,其次序不能任意顛倒。二叉樹是遞迴定義的,因此,與二叉樹有關的題目基本都可以用遞迴思想解決,當然有些題

重建——面試題6《劍指offer》

題目描述:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。  /** * Def

試題的遍歷方式

一、基本概念 1、二叉樹的概念 一棵二叉樹是結點的一個有限集合,該集合或者為空,或者是由一個根節點加上兩棵分別稱為左子樹和右子樹的二叉樹組成(即一個根節點最多隻有兩個孩子結點)。 2、二叉樹的特點 (1)每個結點最多有兩棵子樹,即二叉樹不存在度大於2的結

試題(一)---判斷兩個結構是否相同

一、首先這個問題是判斷二叉樹的結構是否相同,所以這就和二叉樹的資料的值無關。只需要判斷結構;判斷兩個二叉樹的結構是否相同很簡單。 採用遞迴的思想: (1)如果兩棵二叉樹都為空,返回真 (2)

試題總結(Java)

本文參考部落格:http://www.jianshu.com/p/0190985635eb 先上二叉樹的資料結構: class TreeNode{ int val; //左孩子 TreeNode left; //右孩子 TreeNo

試題--已知的兩種遍歷序列,求出另一種遍歷序列

已知先序遍歷序列和中序遍歷序列,求出後序序列   或者   已知中序序列和後序序列 , 求出先序遍歷。。都是一些考試中容易考的題目。 經過研究發現,已知先序序列和後序序列,無法唯一確定一棵樹,所以就無

輕鬆搞定試題

樹是一種比較重要的資料結構,尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之分,其次序不能任意顛倒。二叉樹是遞迴定義的,因此,與二叉樹有關的題目基本都可以用遞迴思想解決

試題

import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.uti

常見的試題

    面試中,最常見是資料結構就是二叉樹和連結串列了,其中和二叉樹有關的常見面試題主要是:樹的前序遍歷、中序遍歷、後序遍歷、分層遍歷、樹的節點數、樹的葉子節點數、樹的第K層節點數、樹的深度、樹的寬度、平衡二叉樹的判定、完全二叉樹的判定、滿二叉樹的判定、由前序中序反推後序遍

試題

1. 前序/中序/後序遍歷(非遞迴) 前序 void PrevOrderNonR() { stack<Node*> s; Node* cur =

【資料結構】---------試題(具體的所有實現)

實現二叉樹的相關的操作: 先序遍歷樹(遞迴) 中序遍歷樹(遞迴) 後序遍歷樹(遞迴) 層序遍歷樹 建立一棵樹 樹的銷燬 樹的拷貝 二叉樹中節點的個數 二叉樹葉子節點的個數 二叉樹第K層節點的個數 樹的高度 在二叉樹中查詢節點 找當前節點的左子樹

【資料結構】試題總結

為了對二叉樹的知識進行鞏固,今天我們來解析5道二叉樹的經典面試題。 這五道面試題如下: 求二叉樹中最遠兩個結點的距離; 判斷一棵樹是否是完全二叉樹; 由前序和中序遍歷序列重建二叉樹 (前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6

試題:前中序求後序、中後序求前序

在面試時,避免不了的會遇到一些資料結構的面試題,今天我們就來了解一下二叉樹的經典面試題: 已知二叉樹的前序遍歷順序為ABCDEGHF,中序遍歷順序為DBAGEHCF,求該二叉樹的後序遍歷。 還有: 已知二叉樹的中序遍歷順序為DBAGEHCF,後序遍歷順序為DBGHEFCA,求該二叉樹的前序遍歷。 類似

騰訊2017暑假試題-查詢的根

/* 騰訊2017暑假筆試題-查詢二叉樹的根 對於一個高度為k的滿排序二叉樹,給定k和三個數, 找到這三個數的最小根節點 */ #include <iostream> #include <vector> #include <algorithm> u

相關的演算法試題

1. 二叉搜尋樹(BST)的後序遍歷序列 2. 序列化/反序列化二叉樹 3. 找到BST中的第k小的數 4. 二叉搜尋樹轉雙鏈表 5. 找出所有節點和滿足目標數的路徑 6.根據二叉樹的前序遍歷和中序遍歷陣列來重建二叉樹 7

c++實現試題(1)

1.建立二叉樹2.前序遍歷<遞迴與非遞迴> 3.中序遍歷<遞迴與非遞迴> 4.後序遍歷<遞迴與非遞迴> 5.層次遍歷  6.獲得節點葉子的個數7.二叉樹獲得的高度8.二叉樹交換的左右兒子9.求兩個節點pNode1和pNode2在以[R為樹

阿里14試題-求一個最大值和最小值的差值絕對值

阿里巴巴面試題: 輸入:一個二叉樹 輸出:二叉樹的最大值和最小值的差值絕對值 單純從演算法功能上來看 1-可以先建立一個大根堆,把最大的元素挑出來; 2-然後在建立小根堆,把最小的元素挑出來; 3-在求最大和最小差值的絕對值; 程式碼: #if 0 /* 最大堆排序 */

算法筆記_189:歷屆試題 橫向打印(Java)

father 比較 fat color title 比對 temp ger 筆記 目錄 1 問題描述 2 解決方案 1 問題描述 問題描述 二叉樹可以用於排序。其原理很簡單:對於一個排序二叉樹添加新節點時,先與根節點比較,若小則交給左子樹繼續處理,否則交給右子樹