恢复一棵二叉查找树

二叉搜索树中有两个节点的值被相互交换,还原一个正常的二叉搜索树。

二叉搜索树,中序遍历,每次遍历的值都会比上次遍历的值小。根据中序遍历的这个性质可以找到值错误的节点,用first表示上一次遍历的节点,用second表示当前遍历的节点,但是我们不能确定到底哪一个才是错误的节点,继续遍历,如果接下来没有发现错误的节点,则交换上次发现的两个错误节点即可。如果接下来又发现了错误的节点,则说明现在遍历的节点和first节点是错误节点,交换两个节点的值。代码如下:

public void recoverTree(TreeNode root) {
    //use inorder traversal to detect incorrect node

    inOrder(root);

    int temp = first.val;
    first.val = second.val;
    second.val = temp;
}

TreeNode prev = null;
TreeNode first = null;
TreeNode second = null;

public void inOrder(TreeNode root){
    if(root == null) return;
    //search left tree
    inOrder(root.left);

    //in inorder traversal of BST, prev should always have smaller value than current value
    if(prev != null && prev.val >= root.val){
        //incorrect smaller node is always found as prev node
        if(first == null) first = prev;
      //incorrect larger node is always found as curr(root) node
        second = root;
    }


    //update prev node
    prev = root;

    //search right tree
    inOrder(root.right);
}

基于morris中序遍历的恢复。O(1)的空间。

public void recoverTree(TreeNode root) {
    //Morris-traversal

    TreeNode first = null;
    TreeNode second = null;

    TreeNode pred = null; //rightmost node in left tree
    TreeNode prev = null; 

    TreeNode curr = root;

    while(curr != null){
        //for each node, we compare it with prev node as we did in in-order-traversal
        if(prev != null && curr.val <= prev.val){
            if(first == null) first = prev;
            second = curr;
        }

        if(curr.left != null){
            //got left tree, then let's locate its rightmost node in left tree
            pred = curr.left;
            //we may have visited the left tree before, and connect the rightmost node with curr node (root node)
            while(pred.right != null && pred.right != curr){
                pred = pred.right;
            }

            if(pred.right == curr){
                //if this left tree has been visited before, then we are done with it
                //cut the connection with currNode and start visit curr's right tree
                pred.right = null;
                prev = curr;
                curr = curr.right;
            }else{
                //if this left tree has not been visited before, then we create a back edge from rightmost node
                // to curr node, so we can return to the start point after done the left tree
                pred.right = curr;
                curr = curr.left;
            }

        }else{
            //no left tree, then just visit its right tree
            prev = curr;
            curr = curr.right;
        }
    }

    int temp = first.val;
    first.val = second.val;
    second.val = temp;
}
    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/guoyuguang0/article/details/51019533
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞