“爬”一棵二叉树

时间:2011-11-06 15:56:53

标签: c++ algorithm binary-tree

有没有办法在没有访问其他分支的情况下直接爬树到数字? 例如,如果我有11号,我必须访问它2到5到11而不是任何搜索。

                                 0
                            /         \
                           /           \
                          /             \
                        1                2
                      /    \           /    \
                     /      \         /      \ 
                    3        4        5       6
                   / \      / \      / \     / \
                  /   \    /   \    /   \   /   \
                 7     8  9    10   11  12  13  14 

我已经杀了很多时间我现在唯一得到的就是获得N号的第一条路线(1或2)你必须(n-1)/ 2直到n等于1或2 。 例: (12 - 1)/ 2 => (5 - 1)/ 2 => 2.(7-1)/ 2 =>(3-1)/ 2 => 1.(11-1)/ 5 =>(2-1)/ 2 => 1。 但最终切断根(0)并像处理新的那样处理2是正确的:

          2
         / \
        /   \
       /     \
     5        6
    / \      / \
   /   \    /   \ 
  11   12  13   14

         to

          0
         / \
        /   \
       /     \
     1        2
    / \      / \
   /   \    /   \ 
  3     4  5     6

解决方案:

int climb(int ID, Tree<int> t)
{

    int time = 0;
    if (tree.exists()) {
        time += t.value();
        tree t1, t2;
        t.branches(t1, t2);
        int branch = ID;
        while (branch > 2) branch = (branch - 1)/2;
        int offset = 1;
        while (offset*2 < ID - 1) offset *= 2;
        if (aux == 1) time += climb(ID - offset2/, a1);
        if (aux == 2) time += climb(ID - offset, a2);
    }
    return time;
}

您可以访问完整二叉树的任何(1,5,13等)元素。

4 个答案:

答案 0 :(得分:1)

如果您想跳过中间的所有节点,请使用哈希容器(例如std::mapstd::set)和哈希搜索。二进制树意味着递归遍历。请注意,set不是关联的,因此您必须稍微解决它。

如果你太努力地将自定义代码/成员变量添加到树/树节点,你可能会得到一个对内存很重的树impl(David回答这是一个非常明亮的例子)。

- 编辑 -

如果您的ID始终是没有太多漏洞的序列(例如0, 1, 2,..., 5068, 69,...,230,231),我建议使用普通的旧阵列!如果您想了解更多信息,请与我们联系。

一般来说,我的信息是首先选择正确的容器/结构,然后只在需要时对结构本身进行“次要”修改。

答案 1 :(得分:0)

我假设您有一个完美的二叉树(所有叶子都在相同的深度,并且每个父亲都有两个孩子),所有节点的值都与您提供的示例相似。

在这种情况下,请注意以下事项:

  
      
  • 节点n具有值为2 * n + 1,2 * n + 2
  • 的节点作为子节点   
  • 如果要转到奇数值为K的节点,则其父节点为节点(K-1)/ 2
  •   
  • 如果要访问具有偶数值K的节点,则其父节点是节点(K-2)/ 2
  •   

您重复相同的过程,因为您到达节点0并且您拥有必须访问的所有节点。

因此,对于您的示例,您希望访问节点11.

11 is odd so its parent is (11-1)/2 = 5
5 is odd so its parent is (5-1)/2 = 2
2 is even so its parent is (2-2)/0 = 0

we have reached the root node, so you have to follow the path 0->2->5->11

答案 2 :(得分:0)

我想“攀爬”到任何分支或叶子而不访问不在路上的分支(如果我爬到'4'那么我直接去0 - > 2 - > 4)。并且只有我错过的路径是偏移,它将“变形”分支到树(见问题)。

我正在接受这样的偏移:

int offset = 1;
while (offset*2 < ID - 1) offset *= 2;

适用于分支'2',offset / 2适用于分支'1'。

int climb(int ID, Tree<int> t)
{

    int time = 0;
    if (tree.exists()) {
        time += t.value();
        tree t1, t2;
        t.branches(t1, t2);
        int branch = ID;
        while (branch > 2) branch = (branch - 1)/2;
        int offset = 1;
        while (offset*2 < ID - 1) offset *= 2;
        if (aux == 1) time += climb(ID - offset2/, a1);
        if (aux == 2) time += climb(ID - offset, a2);
    }
    return time;
}

答案 3 :(得分:0)

其他方式是制作筹码:

void solve(int n)
{
  stack<direction> path;
 //Calculate the way 
  while (n > 0)
  {
    if (n & 1) // if n is odd;
      path.push_back(left);
    else
      path.push_back(right);

    n = (n - 1) / 2;
  }

  //Do actual "climbing"

  while (!path.empty())
  {
    if (path.top() == left)
    {
      go left
    }
    else
    {
      go right
    }

    path.pop();
  }
}

来自linux.org.ru的Raving_Zealot