"Climbing"二叉树

"Climbing" a binary tree

本文关键字:二叉树 Climbing      更新时间:2023-10-16

是否有某种方法可以直接爬到树而不访问其他分支?例如,如果我有数字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等)元素

如果您想跳过所有节点之间使用哈希容器(例如std::mapstd::set)和哈希搜索。二叉树是用来递归遍历的。请注意,set不是关联的,所以你必须围绕它工作一点。

如果你太努力地在树/树节点中添加自定义代码/成员变量,你可能会得到一个占用大量内存的树式隐含(David的回答就是一个很好的例子)。

—edit—

如果你的id总是一个没有太多漏洞的序列(例如0, 1, 2,..., 5068, 69,...,230,231),我建议使用普通的旧数组!如果你想知道更多,请告诉我。

一般来说,我的建议是首先选择正确的容器/结构,然后只有在需要时才对结构本身进行"轻微"修改。

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

在本例中,注意以下内容:

  • 节点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

我想"爬"到任何分支或叶子,而不访问不妨碍的分支(如果我爬到'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;
}

另一种方法是创建堆栈:

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();
  }
}

感谢Raving_Zealot from linux.org.ru