C++ 在BST中查找交换的节点
我正在尝试编写一个程序,可以检测和打印BST中已交换的两个节点 在一个三层树中,我使用这种方法接近解决方案C++ 在BST中查找交换的节点,c++,algorithm,data-structures,tree,binary-search-tree,C++,Algorithm,Data Structures,Tree,Binary Search Tree,我正在尝试编写一个程序,可以检测和打印BST中已交换的两个节点 在一个三层树中,我使用这种方法接近解决方案 If (!AllSubTreeAreValid()) { //Nodes swapped on same side of main root node } else { int max = getMax(root->left); int min = getMin(root->right); if(max > root->data || min <
If (!AllSubTreeAreValid())
{
//Nodes swapped on same side of main root node
}
else
{
int max = getMax(root->left);
int min = getMin(root->right);
if(max > root->data || min < root->data )
{
//Nodes swapped on different sides of main root node
//Print max and min values
}
else
{
//No node swappped
}
}
//Helper functions
int GetMaxEle(TreeNode* tree)
{
while(tree->right!=NULL)
{
tree=tree->right;
}
return tree->info;
}
int GetMinEle(TreeNode* tree)
{
while(tree->left!=NULL)
{
tree=tree->left;
}
return tree->info;
}
在根节点15的右子树中,12更大(违例)
在根节点15的左子树中,16更大(违例)
那么,16、12是上述BST中交换的元素。我如何通过程序找到它们 我猜你的getMin et getMax与树是BST的假设是一致的,所以
T getMax(tree) {
return tree -> right == null
? tree -> value
: getMax(tree -> right);
}
(或具有循环的等效代码)。
如果是这样,代码最多检查树中的三个值。即使getMax和getMin遍历整个树以获得实际的max/min,您的测试仍然只基于两个比较。如果您想检查您的树是否满足BST属性,很明显,您必须检查所有的值。它足以将每个节点与其父节点进行比较
void CheckIsBst(Tree *tree) {
if (tree -> left != null) {
if (tree -> left -> value > tree -> value) {
// print violation
}
CheckIsBst(tree -> left);
}
// same with -> right, reversing < to > in the test
}
void CheckIsBst(树*Tree){
如果(树->左!=空){
如果(树->左->值->树->值){
//打印冲突
}
选中ISBST(树->左);
}
//与->右侧相同,在测试中反转
}
编辑:这是错误的,请参阅评论。我相信这个没问题
void checkIsBst(Tree *Tree, Tree *lowerBound, Tree *upperBound) {
if(lowerBound!= null && lowerBound -> value > tree -> Value) {
//violation
}
// same for upper bound, check with <
if (tree -> left != null) {
if (tree -> left -> value > tree -> value) {
// print violation
}
CheckIsBst(tree -> left, lowerBound, tree);
}
// same for right, reversing comparison
// setting lowerBound to tree instead of upperBound
}
void checkIsBst(树*Tree,树*lowerBound,树*upperBound){
if(lowerBound!=null&&lowerBound->value>tree->value){
//违反
}
//上限相同,请与检查<
如果(树->左!=空){
如果(树->左->值->树->值){
//打印冲突
}
选中ISBST(树->左,下边框,树);
}
//右侧相同,反向比较
//将lowerBound设置为tree而不是Upper Bound
}
使用空边界从根调用考虑此问题的一种方法是使用这样一个事实,即树的无序遍历将按排序顺序生成所有元素。如果您可以在此漫游过程中检测到与排序顺序的偏差,则可以尝试定位位于错误位置的两个元素 让我们先看看如何对一个简单的排序数组执行此操作,然后将使用我们的算法构建在树上工作的东西。直观地说,如果我们从一个排序的数组开始,然后交换两个(不相等的!)元素,我们最终会发现数组中的一些元素不合适。例如,给定数组
1 2 3 4 5
如果我们交换2和4,我们将得到以下数组:
1 4 3 2 5
我们如何检测到2和4在这里交换?因为4是两个元素中较大的一个,并且向下交换,所以它应该大于它周围的两个元素。类似地,因为2被交换了,所以它应该比它周围的两个元素都小。由此,我们可以得出结论,2和4被交换了
但是,这并不总是正确的。例如,假设我们交换1和4:
4 2 3 1 5
这里,2和1都比它们的相邻元素小,4和3都比它们的相邻元素大。从这一点我们可以看出,这四个中有两个不知怎么被交换了,但我们不清楚应该交换哪一个。然而,如果我们取这些值中的最大值和最小值(分别为1和4),我们最终会得到交换的一对
更一般地说,要查找在序列中交换的元素,您需要查找
- 阵列中最大的局部最大值
- 数组中最小的局部最小值
20
/ \
15 30
/ \ / \
10 17 25 33
/ | / \ / \ | \
9 16 12 18 22 26 31 34
如果我们把它线性化成一个数组,我们得到
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
请注意,16大于其周围元素,12小于其周围元素。这立即告诉我们12和16被交换了
因此,解决这个问题的一个简单算法是对树进行有序遍历,将其线性化为一个序列,如向量
或deque
,然后扫描该序列以找到最大的局部最大值和最小的局部最小值。这将在O(n)时间内运行,使用O(n)空间。一个更复杂但更节省空间的算法是一次只跟踪三个节点——当前节点、其前一个节点和后一个节点——这将内存使用率降低到O(1)
希望这有帮助 如果您确定只有一个交换,则templatetypedef完成的树遍历将起作用。否则,我建议基于初始代码的解决方案:
int GetMax(TreeNode* tree) {
int max_right, max_left, ret;
ret = tree->data;
if (tree->left != NULL) {
max_left = GetMax(tree->left);
if (max_left > ret)
ret = max_left;
}
if (tree->right != NULL) {
max_right = GetMax(tree->right);
if (max_right > ret)
ret = max_right;
}
return ret;
}
int GetMin(TreeNode* tree) {
int min_right, min_left, ret;
ret = tree->data;
if (tree->left != NULL) {
min_left = GetMin(tree->left);
if (min_left < ret)
ret = min_left;
}
if (tree->right != NULL) {
min_right = GetMin(tree->right);
if (min_right < ret)
ret = min_right;
}
return ret;
}
void print_violations(TreeNode* tree) {
if ((tree->left != NULL) && (tree->right != NULL)) {
int max_left = GetMax(tree->left);
int min_right = GetMin(tree->right);
if (max_left > tree->data && min_right < tree->data) {
printf("Need to swap %d with %d\n", max_left, min_right);
}
}
if (tree->left != NULL)
print_violations(tree->left);
if (tree->right != NULL)
print_violations(tree->right);
}
intgetmax(树节点*tree){
int max_right,max_left,ret;
ret=树->数据;
如果(树->左!=空){
max_left=GetMax(树->左);
如果(最大左>后)
ret=左最大值;
}
如果(树->右!=空){
max\u right=GetMax(树->右);
如果(最大右>返回)
ret=最大向右;
}
返回ret;
}
int GetMin(树节点*tree){
int minu_right,minu left,ret;
ret=树->数据;
如果(树->左!=空){
min_left=GetMin(树->左);
如果(最小左右!=空){
min_right=GetMin(树->右);
如果(最小右左!=NULL)&&(树->右!=NULL)){
int max_left=GetMax(树->左);
int min_right=GetMin(树->右);
如果(最大左>树->数据和最小右<树->数据){
printf(“需要将%d与%d交换\n”,左最大,右最小);
}
}
如果(树->左!=空)
打印违规(树->左);
如果(树->右!=空)
打印冲突
int GetMax(TreeNode* tree) {
int max_right, max_left, ret;
ret = tree->data;
if (tree->left != NULL) {
max_left = GetMax(tree->left);
if (max_left > ret)
ret = max_left;
}
if (tree->right != NULL) {
max_right = GetMax(tree->right);
if (max_right > ret)
ret = max_right;
}
return ret;
}
int GetMin(TreeNode* tree) {
int min_right, min_left, ret;
ret = tree->data;
if (tree->left != NULL) {
min_left = GetMin(tree->left);
if (min_left < ret)
ret = min_left;
}
if (tree->right != NULL) {
min_right = GetMin(tree->right);
if (min_right < ret)
ret = min_right;
}
return ret;
}
void print_violations(TreeNode* tree) {
if ((tree->left != NULL) && (tree->right != NULL)) {
int max_left = GetMax(tree->left);
int min_right = GetMin(tree->right);
if (max_left > tree->data && min_right < tree->data) {
printf("Need to swap %d with %d\n", max_left, min_right);
}
}
if (tree->left != NULL)
print_violations(tree->left);
if (tree->right != NULL)
print_violations(tree->right);
}