如何二叉树转换为就地二叉搜索树,即我们不能使用任何额外的空间。

有帮助吗?

解决方案

您不会过多去,但如果要求是什么,我觉得是,你有一个二叉树已经创建并坐在内存,但不排序(你希望它是排序的方式,反正)。

我假设树节点看起来像

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

我也假设你能READ C

虽然我们可以只是坐在那里不知道为什么这棵树没有排序顺序不我们有什么好处,所以我会忽略它,只是应付排序它已经创建了有史以来创造。

这没有多余的空间中使用的要求是奇数。暂时会有额外的空间,如果只是堆栈。我会认为这意味着调用malloc或类似的东西,也该得到的树有使用没有更多的内存比原来的无序树。

在第一和最简单的解决方案是做一个序遍历所述未分类的树中除去从该树中的每个节点和做一个排序插入一个新的树的。这是O(N + N 的log(n)),这是O(n 的log(n))。

如果这是他们想要的不是和你将不得不使用的旋转和东西.....这太可怕了!

我认为你可以做一个堆排序的奇版本做到这一点,但我遇到了问题。 这并想到另一件事,这将是可怕的慢,就做的树冒泡排序的一个奇怪的版本。

有关这个每个节点相比,可能与每个交换它的直接的儿童(因此也与其父),直到你遍历树并没有发现任何 需要的互换。这样做的这个版本摇床排序(即那张左至右和从右向左冒泡排序)将效果最好,最初的传球后,你会不会需要向下遍历子树方面没有看的顺序出它的父

我敢肯定,无论是这个algorthm在我面前想出了别人,并有一个很酷的名字,我只是不知道,或者说,它以某种方式说,我没有看到根本性的缺陷。

未来与用于第二建议的运行时计算。是一个相当复杂的。起初,我认为,这将仅仅是为O(n ^ 2),如泡沫和振动筛排序,但我不能满足自己的子树遍历避免可能无法赢得足够让它更好一点比为O(n ^ 2)。从本质上讲泡沫和振动筛排序得到这个优化过,但仅在总有序性的早期出现结束,你可以砍掉限制。有了这个树的版本,你得到机会为可能避免块集合中的中间也是如此。嗯,就像我说的,它可能是致命的缺陷。

其他提示

转换二叉树到双重链接列表 - 可以在O(n)的处理完毕就地结果 在排序使用归并排序,nlogn结果 转换列表回树 - O(n)的

简单nlogn溶液。

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

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)使用上述算法以找出inoder第一节点的后继者。 c)中重复步骤2的所有返回的继任者。

使用上述2算法,并执行在二叉树序遍历,而无需使用额外的空间。 做遍历时形成的二叉搜索树。但复杂性是O(N2)最坏的情况。

好吧,如果这是一个面试问题,第一件事我会脱口而出(零实际想法)是这样的:迭代整个二进制递归和找到的最小元素。把它拿出来的二叉树。现在,重复,你遍历整个树,并找到最小的元素的过程中,并添加它作为最后一个元素的父发现(与前元素成为新节点的左子)。重复多次,直到所需的原树是空的。最后,你只剩下最坏的排序二叉树 - 链表。您的指针指向根节点,这是最大的元件。

这是一个可怕的算法全能 - 为O(n ^ 2)运行时间,最坏的可能二叉树输出,但它是一个不错的起点,想出更好的东西之前,有你能够编写的优势在白板上的大约20行它的代码。

一个二叉树通常就是二叉搜索树,在这种情况下需要任何转换。

也许你需要澄清你是从什么转换的结构。是您的源代码树不平衡?难道不是你想要搜索的键排序?你是如何得出的源代码树?

#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;
}
struct Node
{
    int value;
    Node* left;
    Node* right;
};

void swap(int& l, int& r)
{
    int t = l;
    l = r;
    r = t;
}

void ConvertToBST(Node* n, Node** max)
{
    if (!n) return;

    // leaf node
    if (!n->left && !n->right)
    {
        *max = n;
        return;
    }

    Node *lmax = NULL, *rmax = NULL;
    ConvertToBST(n->left, &lmax);
    ConvertToBST(n->right, &rmax);

    bool swapped = false;
    if (lmax && n->value < lmax->value)
    {
        swap(n->value, lmax->value);
        swapped = true;
    }

    if (rmax && n->value > rmax->value)
    {
        swap(n->value, n->right->value);
        swapped = true;
    }

    *max = n;
    if (rmax && rmax->value > n->value) *max = rmax;

    // If either the left subtree or the right subtree has changed, convert the tree to BST again
    if (swapped) ConvertToBST(n, max);
}

待办事项序的二进制树的遍历和存储结果。 排序结果acending顺序 形成由作为根取排序列表的中间元素(这可以通过使用二进制搜索来完成的)二叉搜索树。所以我们得到平衡二叉搜索树。

堆排序树.. nlogn复杂..

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top