Konvertierung des binären Q36-Suchbaums und der doppelt verknüpften Liste

Konvertierung zwischen binärem Suchbaum und doppelt verknüpfter Liste

Titel

Geben Sie einen binären Suchbaum ein, um den binären Suchbaum in eine sortierte doppelt verknüpfte Liste umzuwandeln. Es ist erforderlich, dass kein neuer Knoten erstellt werden kann und nur der Zeiger des Knotenzeigers im Baum angepasst werden kann.

Ideen

Die Durchlaufsequenz des binären Suchbaums mittlerer Ordnung ist die erforderliche verknüpfte Liste.

4
2
6
1
3
5
7
4
2
6
1
3
5
7

Verwenden Sie die Idee der Rekursion, um das Ende einer sich ständig ändernden Liste beizubehalten:

  1. Konvertieren Sie zuerst den linken Teilbaum des Wurzelknotens, um die letzte Position der verknüpften Liste zu erhalten.
  2. Wenn das Ende der verknüpften Liste nicht leer ist, wird eine Verknüpfung zum Stammknoten hergestellt, und das letzte Bit wird zum Stammknoten
  3. Transformieren Sie dann rekursiv den richtigen Teilbaum.
  4. Kehren Sie schließlich zum Ende der Liste zurück
  5. Da es sich um eine doppelt verknüpfte Liste handelt, können Sie den Kopf der verknüpften Liste in umgekehrter Reihenfolge abrufen.

Erreichen

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
       if(pRootOfTree==nullptr) return nullptr;
        TreeNode* listEnd = nullptr;
        //递归得到链表
        ConvertCore(pRootOfTree, &listEnd);
        //从尾获取头
        while(listEnd!=nullptr && listEnd->left!=nullptr)
            listEnd = listEnd->left;
        return listEnd;
    }
    
    void ConvertCore(TreeNode* pRootOfTree, TreeNode** listEnd)
    {
        if(pRootOfTree==nullptr) return;
        //转换左子树
        if(pRootOfTree->left != nullptr)
            ConvertCore(pRootOfTree->left, &(*listEnd));
        //append root
        if((*listEnd) != nullptr){
            (*listEnd)->right = pRootOfTree;
            pRootOfTree->left = (*listEnd);
        }
        //改变链表尾端
        (*listEnd) = pRootOfTree;
        //转换右子树
        if(pRootOfTree->right != nullptr)
            ConvertCore(pRootOfTree->right, &(*listEnd));
    }
};
链接:https://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5
来源:牛客网

方法一:非递归版
解题思路:
1.核心是中序遍历的非递归算法。
2.修改当前遍历节点与前一遍历节点的指针指向。
    import java.util.Stack;
    public TreeNode ConvertBSTToBiList(TreeNode root) {
        if(root==null)
            return null;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode p = root;
        TreeNode pre = null;// 用于保存中序遍历序列的上一节点
        boolean isFirst = true;
        while(p!=null||!stack.isEmpty()){
            while(p!=null){
                stack.push(p);
                p = p.left;
            }
            p = stack.pop();
            if(isFirst){
                root = p;// 将中序遍历序列中的第一个节点记为root
                pre = root;
                isFirst = false;
            }else{
                pre.right = p;
                p.left = pre;
                pre = p;
            }      
            p = p.right;
        }
        return root;
    }
方法二:递归版
解题思路:
1.将左子树构造成双链表,并返回链表头节点。
2.定位至左子树双链表最后一个节点。
3.如果左子树链表不为空的话,将当前root追加到左子树链表。
4.将右子树构造成双链表,并返回链表头节点。
5.如果右子树链表不为空的话,将该链表追加到root节点之后。
6.根据左子树链表是否为空确定返回的节点。
    public TreeNode Convert(TreeNode root) {
        if(root==null)
            return null;
        if(root.left==null&&root.right==null)
            return root;
        // 1.将左子树构造成双链表,并返回链表头节点
        TreeNode left = Convert(root.left);
        TreeNode p = left;
        // 2.定位至左子树双链表最后一个节点
        while(p!=null&&p.right!=null){
            p = p.right;
        }
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表
        if(left!=null){
            p.right = root;
            root.left = p;
        }
        // 4.将右子树构造成双链表,并返回链表头节点
        TreeNode right = Convert(root.right);
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后
        if(right!=null){
            right.left = root;
            root.right = right;
        }
        return left!=null?left:root;       
    }
方法三:改进递归版
解题思路:
思路与方法二中的递归版一致,仅对第2点中的定位作了修改,新增一个全局变量记录左子树的最后一个节点。
    // 记录子树链表的最后一个节点,终结点只可能为只含左子树的非叶节点与叶节点
    protected TreeNode leftLast = null;
    public TreeNode Convert(TreeNode root) {
        if(root==null)
            return null;
        if(root.left==null&&root.right==null){
            leftLast = root;// 最后的一个节点可能为最右侧的叶节点
            return root;
        }
        // 1.将左子树构造成双链表,并返回链表头节点
        TreeNode left = Convert(root.left);
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表
        if(left!=null){
            leftLast.right = root;
            root.left = leftLast;
        }
        leftLast = root;// 当根节点只含左子树时,则该根节点为最后一个节点
        // 4.将右子树构造成双链表,并返回链表头节点
        TreeNode right = Convert(root.right);
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后
        if(right!=null){
            right.left = root;
            root.right = right;
        }
        return left!=null?left:root;       
    }
Veröffentlichte 58 Originalartikel · gewann 11 · 30.000+ Aufrufe

Ich denke du magst

Origin blog.csdn.net/mhywoniu/article/details/105606168
Empfohlen
Rangfolge