如何从某些节点有效地生成二叉树?

时间:2017-04-08 16:02:06

标签: algorithm tree binary-tree binary-search-tree graph-algorithm

不确定这是否是一个适当的地方可以提出这样的问题..但我还是会发布它...

假设我有一个二叉树,某些节点标记为red

     n1
    /  \
   red n2
   / \  \
  n3 n4  red
         / \
        n5 n6

所以我想做的是,每个red节点,将树生成两个新树,并将每个子树放入一棵树。

因此对于上述情况,它会变成这样的四棵树:

  n1
 / \
n3  n2
    /
   n5

  n1
 / \
 n4 n2
    /
   n5

  n1
 / \
n3  n2
     \
     n6

  n1
 / \
 n4 n2
     \
     n6

这似乎是一个非常清晰的问题..但到目前为止,我还是无法为此提出一个好的解决方案..

有人能解决这个问题吗?非常感谢你!

3 个答案:

答案 0 :(得分:2)

由于二叉树可以表示为线性表达式二叉树

   n1
  /  \
 red n2
 / \  \
n3 n4  red
       / \
      n5 n6

可以表示为线性表达式((n3 red n4) n1 (n2 (n5 red n6)))

现在,二叉树的线性表达式可以表示为BNF,red可以替换为|或运算符

<s> ::= <a> n1 (n2 <b>)
<a> ::= n3 | n4
<b> ::= n5 | n6

现在这个BNF的所有可能组合(步行)都是

n3 n1 (n2 n5)
n3 n1 (n2 n6)
n4 n1 (n2 n5)
n4 n1 (n2 n6)

这些可以回到你答案的树上。

答案 1 :(得分:2)

一些可以导致清洁实施的观察结果:

  • 如果有n个红色节点,则会有2个 n 树(这忽略了红色节点是叶子的情况 - 这些可能并不重要并且可以通过预处理步骤消除。)
  • 0到2之间的任何数字k n - 1可以代表一种配置 - 在i th 红色节点上做出的决定( ie 是否保留左或右子树)由k的i th 位指示。通过将k & (1 << i)与0进行比较,可以使用逐位运算例如轻松获得此位。

可以逐个生成树的主要功能如下所示:

void spawnAllTrees(baseTree) {
    int nRed = countRedNodes(baseTree);

    // this assigns to each red node an index between 0 and nRed - 1
    // (e.g. according to a pre-order tree traversal). 
    // it computes a hash map denoted as "redIndex" which
    // stores the mapping from Node to int
    computeRedIndices(baseTree);

    for (int k = 0; k < (1 << nRed); k++) {
        crtTree = spawnTree(baseTree, k);
    }
}

spawnTree的代码是:

Node spawnTree(baseTreeNode, k) {
    if (baseTreeNode.isRed()) {
        idx = redIndex[baseTreeNode];
        if (!bitIsSet(k, idx)) {
            return spawnTree(baseTreeNode->left(), k);
        } else {
            return spawnTree(baseTreeNode->right(), k);
    } else {
        return new Node(baseTreeNode->value(), 
                        spawnTree(baseTreeNode->left(), k), 
                        spawnTree(baseTreeNode->right(), k));
    }
}

修改

稍微改变算法 - 递增计数器以确定当前红色节点索引无效。某个红色节点上的不同决策可能会使另一个红色节点接收不同配置的不同索引。

答案 2 :(得分:1)

以下是算法:

node main_root_address; //address of very first node

function myfunc_inorder(root_address) //call this from main 
{
  if root_address is null return;

  myfunc_inorder(root_address->left);

  if(root_address->value is "red")
  {
    node temp = root_address;
    root_previous->parent = root_address->left;
    //inside each node along with value and pointer to left and right             subtree store the address of the parent node.
    myfunc_inorder(main_root_address);
    root_previous->parent = root_address->right;
    myfunc_inorder(main_root_address);
    root_address = temp;
  }

  myfunc_inorder(root_address->right);
}

此算法如何运作?

首先我将从“节点n1”开始,然后转到“节点红色”然后转到“节点n3”然后再回到“节点红色”......这里我将用左子树替换“红色”然后使用右子树并重复算法直到没有留下红色......