C 如何在二叉搜索树中查找交换的节点?

C 如何在二叉搜索树中查找交换的节点?,c,algorithm,C,Algorithm,这是一个面试问题 给出了一个二叉搜索树,并交换了两个节点的值。问题是如何在树的单个遍历中找到节点和交换的值 我试图用下面的代码解决这个问题,但我无法停止递归,所以我遇到了分段错误。帮助我如何停止递归 #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <stdlib.h> /* A binary tree node has data, pointer to le

这是一个面试问题

给出了一个二叉搜索树,并交换了两个节点的值。问题是如何在树的单个遍历中找到节点和交换的值

我试图用下面的代码解决这个问题,但我无法停止递归,所以我遇到了分段错误。帮助我如何停止递归

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdlib.h>

 /* A binary tree node has data, pointer to left child
 and a pointer to right child */
 struct node
{
 int data;
 struct node* left;
 struct node* right;
};
/* Helper function that allocates a new node with the
 given data and NULL left and right pointers. */
 struct node* newNode(int data)
 {
  struct node* node = (struct node*)
                    malloc(sizeof(struct node));
 node->data = data;
 node->left = NULL;
 node->right = NULL;
 return(node);
 }
void modifiedInorder(struct node *root, struct node **nextNode)
 {
    static int nextdata=INT_MAX;
    if(root)
    {       
        modifiedInorder(root->right, nextNode);
        if(root->data > nextdata)
        return;
        *nextNode = root;
        nextdata = root->data;

        modifiedInorder(root->left, nextNode);          
    }
}

void inorder(struct node *root, struct node *copyroot, struct node **prevNode)
{
    static int prevdata = INT_MIN; 
    if(root)
    {
        inorder(root->left, copyroot, prevNode);
        if(root->data < prevdata)
        {
            struct node *nextNode = NULL;
            modifiedInorder(copyroot, &nextNode);

            int data = nextNode->data;
            nextNode->data = (*prevNode)->data;
            (*prevNode)->data = data;
            return;
        }
        *prevNode = root;
        prevdata = root->data;
        inorder(root->right, copyroot, prevNode);           
    }
}

/* Given a binary tree, print its nodes in inorder*/
void printInorder(struct node* node)
{
    if (node == NULL)
        return;

    /* first recur on left child */
    printInorder(node->left);

    /* then print the data of node */
    printf("%d ", node->data);

    /* now recur on right child */
    printInorder(node->right);
}


int main()
{
    /*   4
        /  \
       2    3
      / \
     1   5
    */

    struct node *root = newNode(1);  // newNode will return a node.
    root->left        = newNode(2);
    root->right       = newNode(3);
    root->left->left  = newNode(4);
    root->left->right = newNode(5);
    printf("Inorder Traversal of the original tree\n ");
    printInorder(root);

    struct node *prevNode=NULL;
    inorder(root, root, &prevNode);

    printf("\nInorder Traversal of the fixed tree \n");
    printInorder(root);

    return 0;

}
#包括
#包括
#包括
#包括
/*二叉树节点有数据,指针指向左边的子节点
和一个指向正确孩子的指针*/
结构节点
{
int数据;
结构节点*左;
结构节点*右;
};
/*使用
给定数据和空的左指针和右指针*/
结构节点*新节点(整型数据)
{
结构节点*节点=(结构节点*)
malloc(sizeof(struct node));
节点->数据=数据;
节点->左=空;
节点->右=空;
返回(节点);
}
void modifiedOrder(结构节点*根,结构节点**下一个节点)
{
静态int nextdata=int_MAX;
如果(根)
{       
修改顺序(根->右,下一个节点);
如果(根->数据>下一个数据)
返回;
*nextNode=根;
nextdata=root->data;
修改顺序(根->左,下一个节点);
}
}
void索引顺序(结构节点*根,结构节点*复制根,结构节点**prevNode)
{
静态int prevdata=int_MIN;
如果(根)
{
顺序(根->左,copyroot,prevNode);
如果(根->数据data;
nextNode->data=(*prevNode)->data;
(*prevNode)->数据=数据;
返回;
}
*prevNode=根;
prevdata=根->数据;
顺序(根->右,copyroot,prevNode);
}
}
/*给定一个二叉树,按顺序打印其节点*/
无效打印顺序(结构节点*节点)
{
if(node==NULL)
返回;
/*第一次复发于左侧儿童*/
打印顺序(节点->左侧);
/*然后打印节点的数据*/
printf(“%d”,节点->数据);
/*现在在正确的孩子身上重现*/
打印顺序(节点->右侧);
}
int main()
{
/*   4
/  \
2    3
/ \
1   5
*/
struct node*root=newNode(1);//newNode将返回一个节点。
根->左=新节点(2);
根->右=新节点(3);
根->左->左=新节点(4);
根->左->右=新节点(5);
printf(“按顺序遍历原始树\n”);
打印顺序(根);
结构节点*prevNode=NULL;
顺序(根、根和节点);
printf(“\n固定树的顺序遍历\n”);
打印顺序(根);
返回0;
}

使用有序遍历走到树。通过使用它,您将对所有元素进行排序,并交换一个大于周围元素的元素

例如,考虑下面的二叉树

          _  20  _
         /         \
      15             30
     /   \         /   \ 
   10    17      25     33
  / |   /  \    /  \    |  \
9  16  12  18  22  26  31  34
首先,我们将其线性化为一个数组,得到

9101615121718202256303334


现在您可以注意到16大于其周围的元素,12小于它们。这立即告诉我们12和16被交换了。

下面的函数通过递归迭代左、右子树来验证树是否为BST,同时收紧边界

我相信可以通过修改来实现上述任务

  • 不是返回false,而是返回temp,即指向节点的指针,该节点使树无法成为BST
  • 将有两个这样的实例给出两个交换的值
  • 编辑:我们需要区分返回true的递归函数和指向被交换节点的指针

    这假设只有两个问题定义中提到的值

    bool validate_bst(tnode *temp, int min, int max)
    {
            if(temp == NULL)
                    return true;
    
            if(temp->data > min && temp->data < max)
            {
                    if( validate_bst(temp->left, min, temp->data) && 
                        validate_bst(temp->right, temp->data, max) )
                            return true;
            }
    
            return false;
    }
    

    我在Geeksforgeks.com上找到了这个问题的另一个解决方案…………伙计们,你们可以查看这个线程,了解下面代码的更多解释

    //BST中的两个节点已交换,请更正BST。
    #包括
    #包括
    /*二叉树节点有数据,指针指向左边的子节点
    和一个指向正确孩子的指针*/
    结构节点
    {
    int数据;
    结构节点*左、*右;
    };
    //交换两个整数的实用函数
    无效交换(int*a,int*b)
    {
    int t=*a;
    *a=*b;
    *b=t;
    }
    /*使用
    给定数据和空的左指针和右指针*/
    结构节点*新节点(整型数据)
    {
    结构节点*节点=(结构节点*)malloc(sizeof(结构节点));
    节点->数据=数据;
    节点->左=空;
    节点->右=空;
    返回(节点);
    }
    //此函数按顺序遍历以找出两个交换的节点。
    //它设置了三个指针,第一、中间和最后。如果交换的节点是
    //相邻,然后第一个和中间包含结果节点
    //否则,第一个和最后一个包含结果节点
    void correctBSTUtil(结构节点*根,结构节点**第一,
    结构节点**中间,结构节点**最后,
    结构节点**prev)
    {
    如果(根)
    {
    //左子树的递归
    correctBSTUtil(根->左、前、中、后、上);
    //如果此节点小于上一个节点,则表示它违反了
    //BST规则。
    如果(*prev&&root->data<(*prev)->data)
    {
    //如果这是第一个冲突,请将这两个节点标记为
    //“第一”和“中间”
    如果(!*第一个)
    {
    *第一个=*上一个;
    *中间=根;
    }
    //如果这是第二个冲突,请将此节点标记为最后一个
    其他的
    *last=根;
    }
    //将此节点标记为上一个节点
    *prev=根;
    //右子树的递归
    correctBSTUtil(根->右、第一、中间、最后、上);
    }
    }
    //修复两个节点交换的给定BST的函数。这
    //函数使用correctBSTUtil()查找两个节点并交换
    //用于修复BST的节点
    void correctBST(结构节点*根)
    {
    //初始化指针n
    
       validate_bst(root, -1, 100); // Basically we pass -1 as min and 100 as max in
                                         // this instance
    
    // Two nodes in the BST's swapped, correct the BST.
    #include <stdio.h>
    #include <stdlib.h>
    
    /* A binary tree node has data, pointer to left child
    and a pointer to right child */
    struct node
    {
    int data;
    struct node *left, *right;
    };
    
    // A utility function to swap two integers
    void swap( int* a, int* b )
    {
    int t = *a;
    *a = *b;
    *b = t;
    }
    
    /* Helper function that allocates a new node with the
    given data and NULL left and right pointers. */
    struct node* newNode(int data)
    {
    struct node* node = (struct node *)malloc(sizeof(struct node));
    node->data = data;
    node->left = NULL;
    node->right = NULL;
    return(node);
    }
    
    // This function does inorder traversal to find out the two swapped nodes.
    // It sets three pointers, first, middle and last.  If the swapped nodes are
    // adjacent to each other, then first and middle contain the resultant nodes
    // Else, first and last contain the resultant nodes
    void correctBSTUtil( struct node* root, struct node** first,
                     struct node** middle, struct node** last,
                     struct node** prev )
    {
    if( root )
    {
        // Recur for the left subtree
        correctBSTUtil( root->left, first, middle, last, prev );
    
        // If this node is smaller than the previous node, it's violating
        // the BST rule.
        if (*prev && root->data < (*prev)->data)
        {
            // If this is first violation, mark these two nodes as
            // 'first' and 'middle'
            if ( !*first )
            {
                *first = *prev;
                *middle = root;
            }
    
            // If this is second violation, mark this node as last
            else
                *last = root;
        }
    
        // Mark this node as previous
        *prev = root;
    
        // Recur for the right subtree
        correctBSTUtil( root->right, first, middle, last, prev );
    }
    }
    
    // A function to fix a given BST where two nodes are swapped.  This
    // function uses correctBSTUtil() to find out two nodes and swaps the
    // nodes to fix the BST
    void correctBST( struct node* root )
    {
    // Initialize pointers needed for correctBSTUtil()
    struct node *first, *middle, *last, *prev;
    first = middle = last = prev = NULL;
    
    // Set the poiters to find out two nodes
    correctBSTUtil( root, &first, &middle, &last, &prev );
    
    // Fix (or correct) the tree
    if( first && last )
        swap( &(first->data), &(last->data) );
    else if( first && middle ) // Adjacent nodes swapped
        swap( &(first->data), &(middle->data) );
    
    // else nodes have not been swapped, passed tree is really BST.
    }
    
    /* A utility function to print Inoder traversal */
    void printInorder(struct node* node)
    {
    if (node == NULL)
        return;
    printInorder(node->left);
    printf("%d ", node->data);
    printInorder(node->right);
    }
    
    /* Driver program to test above functions*/
    int main()
    {
    /*   6
        /  \
       10    2
      / \   / \
     1   3 7  12
     10 and 2 are swapped
    */
    
    struct node *root = newNode(6);
    root->left        = newNode(10);
    root->right       = newNode(2);
    root->left->left  = newNode(1);
    root->left->right = newNode(3);
    root->right->right = newNode(12);
    root->right->left = newNode(7);
    
    printf("Inorder Traversal of the original tree \n");
    printInorder(root);
    
    correctBST(root);
    
    printf("\nInorder Traversal of the fixed tree \n");
    printInorder(root);
    
    return 0;
    }
    Output:
    
     Inorder Traversal of the original tree
     1 10 3 6 7 2 12
     Inorder Traversal of the fixed tree
     1 2 3 6 7 10 12
     Time Complexity: O(n)
    
    struct node *correctBST( struct node* root )
    {
    //add code here.
        if(!root)return root;
        struct node* r = root;
        stack<struct node*>st;
       // cout<<"1"<<endl;
        struct node* first = NULL;
        struct node* middle = NULL;
        struct node* last = NULL;
        struct node* prev = NULL; 
        while(root  || !st.empty()){
            while(root){
                st.push(root);
                root = root->left;
            }
            root = st.top();
            st.pop();
            if(prev && prev->data > root->data){
                if(!first){
                    first = prev;
                    middle = root;
                }
                else{
                    last = root;
                }
            }
            prev = root;
            root = root->right;
        }
        if(first && last){
            swap(first->data,last->data);
        }
        else{
            swap(first->data,middle->data);
        }
        return r;
    }
    
          6 
        /  \ 
       10    2 
      / \   / \ 
     1   3 7  12 
    
          6 
        /  \ 
       10    8 
      / \   / \ 
     1   3 7  12