1. 程式人生 > >劍指Offer-26.二叉搜尋樹與雙向連結串列(Javascript)

劍指Offer-26.二叉搜尋樹與雙向連結串列(Javascript)

26.二叉搜尋樹與雙向連結串列

題目連結

題目描述

輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。

解題思路

  • 因為要對二叉搜尋樹重新排序為雙向連結串列,因此可以看出此題應當用中序遍歷,看到樹的題目,基本要想到遞迴和前中後序遍歷。

  • 兩種解題思路,均基於遞迴。

  • 這裡要注意:C++的指標類解法不能直接用於js,因為js的非基本資料型別的傳遞問題~ 可能會出錯~

Code

  • 解法一: 基礎的遞迴
  1. 構建左子樹為雙向連結串列,返回連結串列頭節點left
  2. 定位到左雙向連結串列最後一個節點
  3. 左雙向連結串列最後一個節點與當前節點雙向連結
  4. 構建右子樹為雙向連結串列,返回連結串列頭結點right
  5. 將右雙向連結串列頭節點和當前節點連線起來
  6. 返回雙向連結串列最左邊的頭節點(即:有left為left,無left為根節點root)
/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Convert(root)
{
    // write code here
    if(!root) return null;
    if(!root.left && !root.right)
return root; //構建左子樹為雙向連結串列,返回連結串列頭節點left var left = Convert(root.left); var tmp = left; //若左子樹存在,則用tmp定位到左雙向連結串列最後一個節點 while(tmp && tmp.right){ tmp = tmp.right; } //若左子樹存在,將左雙向連結串列最後一個節點和當前節點連線起來 //注意這裡,tmp與left的存在與否完全相同 if(tmp){ tmp.right =
root; root.left = tmp; } //構建右子樹為雙向連結串列,返回連結串列頭結點right var right = Convert(root.right); //將右雙向連結串列頭節點和當前節點連線起來 if(right){ right.left = root; root.right = right; } //若有左子樹,返回的永遠是最左邊的葉子節點(也就是最小的節點),若無左子樹,則根節點就是最小的節點 return left?left:root; }
  • 解法二: 使用全域性變數leftLast來表示左雙向連結串列的最後一個節點(也就是上一種解法中的tmp)
/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
var leftLast;
function Convert(root)
{
    // write code here
    if(!root){
        return null;
    }
    //返回最左邊的頭節點,並且此時左雙向連結串列的最後一個節點也是該節點
    if(root == null && root == null){
        leftLast = root;
        return root;
    }
    
    //構建左子樹為雙向連結串列,返回連結串列頭節點left
    var left = Convert(root.left);
    
    //若左子樹存在,則將左雙向連結串列最後一個節點與當前節點連線起來
    //這裡,leftLast和left的存在與否並不完全一致哦!
    if(left){
        leftLast.right = root;
        root.left = leftLast;
    }
    
    //那麼此時不論有沒有left,左雙向連結串列的最後一個節點都是當前root啦
    leftLast = root;
    
    //構建右子樹為雙向連結串列,返回連結串列頭結點right
    var right = Convert(root.right);
    
    //將右雙向連結串列頭節點和當前節點連線起來
    if(right){
        right.left = root;
        root.right = right;
    }
    
    //若有左子樹,返回的永遠是最左邊的葉子節點(也就是最小的節點),若無左子樹,則根節點就是最小的節點
    return left?left:root;
}