Conversion of Q36 binary search tree and doubly linked list

Conversion between binary search tree and doubly linked list

topic

Enter a binary search tree to convert the binary search tree into a sorted doubly linked list. It is required that no new node can be created, and only the pointer of the node pointer in the tree can be adjusted.

Ideas

The binary search tree's mid-order traversal sequence is the required linked list.

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

Use the idea of ​​recursion to maintain the end of a constantly changing list:

  1. First convert the left subtree of the root node to get the last position of the linked list.
  2. If the end of the linked list is not empty, it links to the root node, and the last bit becomes the root node
  3. Then recursively transform the right subtree.
  4. Finally, return to the end of the list
  5. Because it is a doubly linked list, you can get the head of the linked list in reverse.

achieve

/*
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;       
    }
Published 58 original articles · won 11 · 30,000+ views

Guess you like

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