二元查找樹轉變成排序的雙向鏈表

聲明:題目來自: http://blog.csdn.net/v_JULY_v/archive/2010/11/17/6015165.aspx   JULY整理了100道微軟等公司的面試題目,我想先不看答案:http://blog.csdn.net/v_JULY_v/archive/2011/01/10/6126406.aspx  自己先做一遍。

 

題目:

 

1.  把二元查找樹轉變成排序的雙向鏈表
 題目:
輸入一棵二元查找樹,將該二元查找樹轉換成一個排序的雙向鏈表。
要求不能創建任何新的結點,只調整指針的指向。
   10
  /  /
 6    14
 / /  / /
4  8 12 16
 轉換成雙向鏈表
4=6=8=10=12=14=16。
 首先我們定義的二元查找樹 節點的數據結構如下:
 
 struct BSTreeNode
{
  int m_nValue; // value of node
  BSTreeNode *m_pLeft; // left child of node
  BSTreeNode *m_pRight; // right child of node
};

 

思路:

 

看一下輸出的雙向鏈表,他的順序和二元查找樹的先序遍歷的順序是一致的,所以一開始我的思路就是用先序遍歷來解這個問題。既然是遞歸,那麼問題肯定能轉換成,要把 節點parent之下(包括節點parent)所代表的二叉樹轉變成雙向鏈表,我們認爲parent的left child 和 right child都已經是轉換好的 雙向鏈表了,所以僞代碼是:

 

preOrderTransform(Parent A)

{

      preOrderTransform(Left Child of Parent A);

      preOrderTransform(Right Child of Parent A);

 

      把 1)左兒子中最大節點, 2)當前Parent節點 ,3)還有 右兒子的最小節點  鏈接起來

}

 

直觀的思路就是 讓preOderTransform(leftChild) 返回左兒子中最大的節點;讓preOrderTransform(rightChild)返回右兒子中最小的節點。但是 問題是: 當parent A所管理的數轉換好以後,它可以作爲祖父節點B 的左字數,也有可能作爲祖父節點B 的右字數,如果作爲B的左子樹,B需要知道A的最大節點,但是處理A的 preOrderTransform(Parent A) 目前並不知道它麾下最大的節點是誰,除非1) 它向右遍歷 (因爲這時候A麾下已經是雙向鏈表,我們可以通過 node=node->m_right 一直找到最右邊的,也就是最大的節點);或者2) 我們想辦法讓A 記住自己的最小和最大節點。

 

我下面的代碼採用了“記住”的方法:

 

代碼:

class BSTreeNode{
 int m_nValue;
 BSTreeNode m_left;
 BSTreeNode m_right;
 
 BSTreeNode(int value){
  m_nValue = value;
 }
}

 

public class BinaryTree2DoubleLink {
 
 
  
   static class Result{
    BSTreeNode head;
    BSTreeNode tail;
   
    public Result(BSTreeNode head, BSTreeNode tail){
     this.head = head;
     this.tail = tail;
    }
   }
  
   BSTreeNode buildTree(){
   
    BSTreeNode root = new BSTreeNode(10);
    root.m_left = new BSTreeNode(6);
    root.m_right = new BSTreeNode(14);
   
    BSTreeNode node = root.m_left;
    node.m_left = new BSTreeNode(4);
    node.m_right = new BSTreeNode(8);
   
    node = root.m_right;
    node.m_left = new BSTreeNode(12);
    node.m_right = new BSTreeNode(16);
   
    return root;
   }
  
  
   //
   Result preOrder(BSTreeNode node){
   
        Result result = new Result(node, node);
   
        if(node == null ){
              return result;
         }
   
         //let's make left child a double linked list
         //leftResult remember the head and tail of the new double linked list
         Result leftResult  = preOrder(node.m_left);
   
   
         //let's make right child a double linked list
         Result rightResult = preOrder(node.m_right);
   
          //link current node with the tail node of left child linked list
          if(leftResult.tail != null){  //注意邊界條件
                  leftResult.tail.m_right = node;
          }
          node.m_left = leftResult.tail;
      
          //link current node with the head node of right child linked list
          if(rightResult.head != null){
                 rightResult.head.m_left = node;
          }
          node.m_right = rightResult.head;
      
          //modify the result after merge current node with both it's left child and right child
      
          if(leftResult.head != null){   //注意邊界條件
                 result.head = leftResult.head;
          }
      
           if(rightResult.tail != null){
                 result.tail = rightResult.tail;
           }
         
           return result;

   }
  
   Result transform(BSTreeNode root){
   
    BSTreeNode head = null;
   
    Result result =  preOrder(root);
    //the order of double linked list is actually the order of pre-order traverse
   
    return result;
   
   }
  
   void print(Result result){
   
    //print from head
    BSTreeNode node = result.head;
    while(node != null){
     System.out.format("%2d ", node.m_nValue);
     node = node.m_right;
    }
    System.out.println();
   
    node = result.tail;
    while(node != null){
     System.out.format("%2d ", node.m_nValue);
     node = node.m_left;
    }
    System.out.println();
   
   }
  
      public static void main(String[] args){
      
       BinaryTree2DoubleLink app = new BinaryTree2DoubleLink();
       BSTreeNode root = app.buildTree();
      
       Result result = app.transform(root);
       app.print(result);
      
      }
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章