Algorithm 如何将二叉树转换为二叉搜索树,也就是说,我们不能使用任何额外的空间

Algorithm 如何将二叉树转换为二叉搜索树,也就是说,我们不能使用任何额外的空间,algorithm,data-structures,tree,binary-tree,binary-search-tree,Algorithm,Data Structures,Tree,Binary Tree,Binary Search Tree,如何将二叉树转换为二叉搜索树,也就是说,我们不能使用任何额外的空间 二叉树通常是二叉搜索树,在这种情况下不需要转换 也许你需要澄清你正在转换的内容的结构。您的源代码树是否不平衡?它不是按您要搜索的密钥排序的吗?你是如何找到源代码树的?如果这是一个采访问题,我会脱口而出的第一件事(没有实际想法)是:递归地迭代整个二进制文件,然后找到最小的元素。把它从二叉树中去掉。现在,重复这个过程,迭代整个树并找到最小的元素,并将其添加为找到的最后一个元素的父元素(前一个元素成为新节点的左子元素)。根据需要重复多

如何将二叉树转换为二叉搜索树,也就是说,我们不能使用任何额外的空间

二叉树通常是二叉搜索树,在这种情况下不需要转换


也许你需要澄清你正在转换的内容的结构。您的源代码树是否不平衡?它不是按您要搜索的密钥排序的吗?你是如何找到源代码树的?

如果这是一个采访问题,我会脱口而出的第一件事(没有实际想法)是:递归地迭代整个二进制文件,然后找到最小的元素。把它从二叉树中去掉。现在,重复这个过程,迭代整个树并找到最小的元素,并将其添加为找到的最后一个元素的父元素(前一个元素成为新节点的左子元素)。根据需要重复多次,直到原始树为空。最后,剩下的是最差的排序二叉树——链表。您的指针指向根节点,它是最大的元素


这是一个非常糟糕的算法,运行时间为O(n^2),二叉树输出可能最差,但在想出更好的算法之前,这是一个不错的起点,它的优点是你可以在白板上用大约20行代码来编写它。

你不需要付出太多努力,但是,如果需求是我认为的,那么您已经创建了一个二叉树,它位于内存中,但没有排序(不管怎样,您希望以什么方式排序)

我假设树节点看起来像

struct tree_node {
    struct tree_node * left;
    struct tree_node * right;
    data_t data;
};
我还假设你能读C

我们可以坐在那里想,为什么这棵树没有按排序顺序创建,这对我们没有任何好处,所以我将忽略它,只处理排序问题

不使用额外空间的要求很奇怪。暂时会有额外的空间,如果只是在堆栈上。我将假设这意味着调用malloc或类似的东西,并且生成的树不需要使用比原始未排序树更多的内存

第一个也是最简单的解决方案是对未排序的树进行预排序遍历,从该树中删除每个节点,并将排序后的插入到新树中。这是O(n+nlog(n)),也就是O(nlog(n))

如果这不是他们想要的,你必须使用旋转和其他方法。。。。。太可怕了

我以为可以通过执行堆排序的奇怪版本来实现这一点,但我遇到了问题。 另一件事出现在我的脑海里,速度非常慢,那就是在树上做一个奇怪的泡泡排序

为此,将对每个节点进行比较,并可能与它的每个直接子节点(因此也与其父节点)重复交换,直到您遍历该树并没有找到任何节点为止 需要互换。执行shaker排序(从左到右和从右到左的气泡排序)版本效果最好,并且在初始传递之后,您不需要向下遍历子树,这些子树看起来不会与其父树的顺序不符

我敢肯定,要么这个算法是我之前的其他人想出的,有一个我不知道的酷名字,要么它在某种程度上有根本性的缺陷,我看不出来


第二个建议的运行时计算相当复杂。起初,我认为它只是O(n^2),就像气泡和振动筛排序一样,但我不能满足自己的要求,子树遍历避免可能不足以使它比O(n^2)好一点。基本上,气泡和振动筛分类也得到了这种优化,但只有在总分类提前出现的末端,你才能削减限制。使用此树版本,您可以获得避免在集合中间的块的可能性。就像我说的,它可能有致命的缺陷。

按顺序遍历二叉树并存储结果。 按顺序对结果排序
通过将排序列表的中间元素作为根来形成二元搜索树(这可以使用二元搜索完成)。因此,我们得到了平衡的二叉搜索树。

执行以下算法以获得解决方案

struct Node * newroot = '\0';

struct Node* PostOrder(Struct Node* root)
{
      if(root != '\0')
      {
          PostOrder(root->left);
          PostOrder(root->right);
          insertBST(root, &newroot);
      }
}

insertBST(struct Node* node, struct Node** root)
{
   struct Node * temp, *temp1;
   if( root == '\0')
   {
      *root == node;
       node->left ==  '\0';
       node->right == '\0';
   }
   else
   {
       temp = *root;
       while( temp != '\0')
       {
           temp1= temp;
           if( temp->data > node->data)
               temp = temp->left;
           else
               temp = temp->right;
       }
       if(temp1->data > node->data)
       {
           temp1->left = node;
       }
       else
       {
           temp1->right = node;
       }
       node->left = node->right = '\0';
    }
}
1) 在不使用任何空格的情况下查找顺序后续项

Node InOrderSuccessor(Node node)
{ 
    if (node.right() != null) 
    { 
        node = node.right() 
        while (node.left() != null)  
            node = node.left() 
        return node 
    }
    else
    { 
        parent = node.getParent(); 
        while (parent != null && parent.right() == node)
       { 
            node = parent 
            parent = node.getParent() 
        } 
        return parent 
    } 
} 
2) 在不使用空格的情况下按顺序遍历

a) 查找顺序遍历的第一个节点。它应该是树的最左边的子级(如果有),或者是第一个右边的子级的左边(如果有),或者右边的子级本身。 b) 使用上述算法查找第一个节点的后续节点。 c) 对所有返回的后继对象重复步骤2

使用上述2种算法,在不使用额外空间的情况下对二叉树进行顺序遍历。
进行遍历时,形成二叉搜索树。但是复杂性是O(N2)最坏的情况。

对树进行堆排序。。nlogn complexity..

执行后序遍历,并从中创建二叉搜索树

struct Node * newroot = '\0';

struct Node* PostOrder(Struct Node* root)
{
      if(root != '\0')
      {
          PostOrder(root->left);
          PostOrder(root->right);
          insertBST(root, &newroot);
      }
}

insertBST(struct Node* node, struct Node** root)
{
   struct Node * temp, *temp1;
   if( root == '\0')
   {
      *root == node;
       node->left ==  '\0';
       node->right == '\0';
   }
   else
   {
       temp = *root;
       while( temp != '\0')
       {
           temp1= temp;
           if( temp->data > node->data)
               temp = temp->left;
           else
               temp = temp->right;
       }
       if(temp1->data > node->data)
       {
           temp1->left = node;
       }
       else
       {
           temp1->right = node;
       }
       node->left = node->right = '\0';
    }
}

将二叉树转换为双链表-可以在O(n)中就地完成
然后使用合并排序,nlogn
将列表转换回树-O(n)

简单的nlogn解决方案。

#包括
#include <stdio.h>
#include <stdlib.h>

typedef int data_t;

struct tree_node {
    struct tree_node * left;
    struct tree_node * right;
    data_t data;
};

        /* a bonsai-tree for testing */
struct tree_node nodes[10] =
{{ nodes+1, nodes+2, 1}
,{ nodes+3, nodes+4, 2}
,{ nodes+5, nodes+6, 3}
,{ nodes+7, nodes+8, 4}
,{ nodes+9, NULL, 5}
,{ NULL, NULL, 6}
,{ NULL, NULL, 7}
,{ NULL, NULL, 8}
,{ NULL, NULL, 9}
        };

struct tree_node * harvest(struct tree_node **hnd)
{
struct tree_node *ret;

while (ret = *hnd) {
        if (!ret->left && !ret->right) {
                *hnd = NULL;
                return ret;
                }
        if (!ret->left ) {
                *hnd = ret->right;
                ret->right = NULL;;
                return ret;
                }
        if (!ret->right) {
                *hnd = ret->left;
                ret->left = NULL;;
                return ret;
                }
        hnd = (rand() &1) ? &ret->left : &ret->right;
        }

return NULL;
}

void insert(struct tree_node **hnd, struct tree_node *this)
{
struct tree_node *ret;

while ((ret= *hnd)) {
        hnd = (this->data  < ret->data ) ? &ret->left : &ret->right;
        }
*hnd = this;
}

void show(struct tree_node *ptr, int indent)
{
if (!ptr) { printf("Null\n"); return; }

printf("Node(%d):\n", ptr->data);
printf("%*c=", indent, 'L');  show (ptr->left, indent+2);
printf("%*c=", indent, 'R');  show (ptr->right, indent+2);
}

int main(void)
{
struct tree_node *root, *this, *new=NULL;

for (root = &nodes[0]; this = harvest (&root);  ) {
        insert (&new, this);
        }

show (new, 0);
return 0;
}
#包括 typedef int data_t; 结构树节点{ 结构树节点*左; 结构树_节点*右; 数据; }; /*测试用盆景树*/ 结构树_节点节点[10]= {{节点+1,节点+2,1} ,{nodes+3,nodes+4,2} ,{nodes+5,nodes+6,3} ,{nodes+7,nodes+8,4} ,{nodes+9,NULL,5} ,{NULL,NULL,6} ,{NULL,NULL,7} ,{NULL,NULL,8} ,{NULL,NULL,9} }; 结构树节点*收获(结构树节点**hnd) { 结构树节点*ret; 而(ret=*hnd){ 如果(!ret->left&&!ret->right){ *hnd=NULL; 返回ret; } 如果(!ret->left){ *hnd=ret->右侧; ret->right=NULL;;
***I am giving this solution in Java***

import javafx.util.Pair;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

public class MinimumSwapRequiredBTintoBST {
    //Node of binary tree
    public static class Node{
        int data;
        Node left;
        Node right;
        public Node(int data){
            this.data = data;
            this.left = null;
            this.right = null;
        }
    }
    public static void main(String []arg){
        root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        System.out.print("Tree traverasl i.e inorder traversal :");
        inorder(root);
        System.out.println(" ");
        MinimumSwapRequiredBTintoBST bst = new MinimumSwapRequiredBTintoBST();
        bst.convertBTBST(root);
    }

    private static void inorder(Node root) {
        if(root == null) return;
        inorder(root.left);
        System.out.print(root.data + "  ");
        inorder(root.right);

    }

   static Node root;
    int[] treeArray;
    int index = 0;

// convert binary tree to binary search tree
    public void convertBTBST(Node node){
        int treeSize = elementsOfTree(node);
        treeArray = new int[treeSize];
        convertBtToArray(node);
        // Sort Array ,Count number of swap

        int minSwap = minimumswap(treeArray);
        System.out.println("Minmum swap required to form BT to BST :" +minSwap);
    }

    private static int minimumswap(int[] arr) {
        int n =arr.length;
        // Create two arrays and use as pairs where first
        // is element and secount array as position of first element
        ArrayList<Pair<Integer, Integer>> arrpos =
            new ArrayList<Pair<Integer, Integer>>();
        // Assign the value
        for(int i =0;i<n;i++)
        {
            arrpos.add(new Pair<Integer, Integer>(arr[i],i));
        }
// Sort the array by array element values to get right
//position of every element as the elements of secound array

        arrpos.sort(new Comparator<Pair<Integer, Integer>>() {
            @Override
            public int compare(Pair<Integer, Integer> o1, Pair<Integer, Integer> o2) {
                return o1.getKey()-o2.getKey();
            }
        });
// To keep track of visited elements .Initially all elements as not visited so put them as false
        int ans = 0;
        boolean []visited = new boolean[n];
        Arrays.fill(visited, false);
        // Traverse array elements
        for(int i =0;i<n;i++){
            // Already swapped and corrected or already present at correct pos
            if(visited[i] || arrpos.get(i).getValue() == i)
                continue;
            // Find out the number of nodes in this cycle and add in ans
            int cycle_size = 0;
            int j =i;
            while(!visited[j]){
                visited[j] = true;
                j = arrpos.get(j).getValue();
                cycle_size++;
            }
            if(cycle_size>0){
                ans += cycle_size-1;
            }
        }
        return ans;
    }

    private void convertBtToArray(Node node) {
        // Check whether tree is empty or not.
        if (root == null) {
            System.out.println("Tree is empty:");
            return;
        }
    else{
        if(node.left != null) {
         convertBtToArray(node.left);}
            treeArray[index] = node.data;
            index++;
            if(node.right != null){
                convertBtToArray(node.right);
            }

        }
    }
    private int elementsOfTree(Node node) {
        int height = 0;
        if(node == null) return 0;
        else{
            height = elementsOfTree(node.left )+ elementsOfTree(node.right)+1;
        }
        return height;
    }


}