给你一个搜索二叉树,如下:
6
/ \
10 2
/ \ / \
1 3 7 12
可以看到 10 和 2 的位置发生了交换。要求设计算法,回复原来的BST。
算法一: http://www.geeksforgeeks.org/fix-two-swapped-nodes-of-bst/
算法二:下面的算法是一个流传很广的算法,但是其实是错误的。首先给出算法,然后给出failure case。
算法二思路:可以借助 isValidBST 的思想,找出被交换的两个节点 。找到之后,把他们交换回去就可以了。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define INT_MIN -100
#define INT_MAX 100
struct Node{
int key; Node* left; Node* right;
Node(int k, Node* l, Node* r): key(k), left(l), right(r){};
};
void correct_helper(Node* root, Node** p1, Node** p2, int min, int max) {
if(root==NULL) return;
else if(root->key < max && root->key > min) {
correct_helper(root->left, p1, p2, min, root->key);
correct_helper(root->right, p1, p2, root->key, max);
}
else {
if(*p1){ *p2 = root; return; }// return after the second invalid node found
else *p1 = root;
}
}
void correct(Node* root) {
Node** p1 = new Node*(NULL);
Node** p2 = new Node*(NULL);
correct_helper(root, p1, p2, -100, 100);
int temp = (*p1)->key;
(*p1)->key = (*p2)->key;
(*p2)->key = temp;
}
int main()
{
Node* n1 = new Node(1, NULL, NULL);
Node* n3 = new Node(3, NULL, NULL);
Node* n7 = new Node(7, NULL, NULL);
Node* n12 = new Node(12, NULL, NULL);
Node* n10 = new Node(10, n1, n3);
Node* n2 = new Node(2, n7, n12);
Node* n6 = new Node(6, n10, n2);
correct(n6);
}
算法二成功的条件是,被交换到两个节点分别位于一个祖先节点的左右子树中。
如果被交换的两个节点的其中一个是另外一个的祖先,算法二就失败了。
下面的二叉树就是个例子:
3
/
4
/
5
上面的二叉树中,3和5被交换。算法二会失败。
3
/
4
/
5
上面的二叉树中,3和5被交换。算法二会失败。