1. 程式人生 > 其它 >劍指offer:26.二叉搜尋樹與雙向連結串列

劍指offer:26.二叉搜尋樹與雙向連結串列

技術標籤:劍指offer連結串列資料結構演算法leetcode

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

題目描述

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

解題思路

  • 下面的思路來自《劍指offer》

將二叉搜尋樹轉換成雙向連結串列即當前結點的左指標指向左子樹的最大結點,右指標指向右子樹的最小節點,如下圖所示:

因此,只需要使用中序遍歷的順序進行轉換(中序遍歷一棵二叉搜尋樹即是從小到大輸出),然後用一個指標pLastNode指向已經轉換的連結串列的最大結點(尾結點)即可,剛開始時這個指標為NULL。由於使用遞迴,當遍歷到當前結點時,左子樹已經完成了轉換,因此,只需讓pLastNode

的右指標指向當前結點,當前結點的左指標指向pLastNode,讓pLastNode指標指向當前結點,然後遞迴右子樹即可。

最後在主函式裡面需要查詢到連結串列的頭結點然後返回頭結點

那個pLastNode指標在整個過程中用來記錄當前已完成轉換的連結串列的未結點,作用相當於一個全域性變數,因此可以用全域性變數來做,或者也可以在主函式中建立這個pLastNode指標變數,然後將這個指標變數的指標傳入呼叫的函式進行修改。如果不用上面兩種方法的話,當前的pLastNode就只能不斷地傳入傳出,增加了很多開銷,這個在寫程式碼的時候自然就能體會到。最好的辦法還是用全域性變數,減少引數傳遞開銷

程式碼

  • 方法一,新手版本,pLastNode
    不斷傳入傳出,產生很多不必要的開銷
/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
private:
    TreeNode* ConvertNode(TreeNode* pNode, TreeNode* pLastNode){
        if(pNode->left)
            pLastNode =
ConvertNode(pNode->left, pLastNode); pNode->left = pLastNode; if(pLastNode) pLastNode->right = pNode; pLastNode = pNode; if(pNode->right) pLastNode = ConvertNode(pNode->right, pLastNode); return pLastNode; } public: TreeNode* Convert(TreeNode* pRootOfTree) { if(pRootOfTree==NULL) return NULL; ConvertNode(pRootOfTree, NULL); while(pRootOfTree->left) pRootOfTree = pRootOfTree->left; return pRootOfTree; } };
  • 方法二,使用指向指標的指標修改主函式中區域性變數pLastNode的值,僅減少傳出開銷
/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
private:
    void ConvertNode(TreeNode* pNode, TreeNode** pLastNode){
        if(pNode->left)
            ConvertNode(pNode->left, pLastNode);
        
        pNode->left = *pLastNode;
        if(*pLastNode) (*pLastNode)->right = pNode;
        *pLastNode = pNode;
        
        if(pNode->right)
            ConvertNode(pNode->right, pLastNode);
    }
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree==NULL) return NULL;
        TreeNode* pLastNode = NULL;
        ConvertNode(pRootOfTree, &pLastNode);
        while(pRootOfTree->left)
            pRootOfTree = pRootOfTree->left;
        
        return pRootOfTree;
    }
};
  • 方法三,使用全域性變數pLastNode,同時減少傳入和傳出開銷
/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
private:
    TreeNode* pLastNode = NULL;
    void ConvertNode(TreeNode* pNode){
        if(pNode->left)
            ConvertNode(pNode->left);
        
        pNode->left = pLastNode;
        if(pLastNode) pLastNode->right = pNode;
        pLastNode = pNode;
        
        if(pNode->right)
            ConvertNode(pNode->right);
    }
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree==NULL) return NULL;
        ConvertNode(pRootOfTree);
        while(pRootOfTree->left)
            pRootOfTree = pRootOfTree->left;
        
        return pRootOfTree;
    }
};