LINUX.ORG.RU

[c++]Помогите написать алгоритм лазания по бинарному дереву

 


0

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

Предположим я хочу забраться на 2 ветку, как мне это сделать без тупого перебора. Я уже слегка залобался искать алгоритмы и жду мнения аналитиков лора.

Пока я вычел у каждого числа 1 представил его как бинарное и забираюсь, на лево если 0 и на право если 1, но не могу забраться на 2 или на один 1.

Помогите решить.

Ответ на: комментарий от CrossFire

нет. Тебе дают число и ты поднимаешься прямо к ветке обазначеной этим числом.

Номер ветки это номер ветки откуда она появилась помноженный на два +1, если ветка с лева, или +2, если справа.

Trieforce
() автор топика
Ответ на: комментарий от quickquest

мне не нужен обход. Мне нужно пройдти только по заданным веткам.

Trieforce
() автор топика
Ответ на: комментарий от Trieforce

>Номер ветки это номер ветки откуда она появилась помноженный на два +1, если ветка с лева, или +2, если справа.

Так ты сам решение написал, что тебе ещё надо?

schizoid ★★★
()

Обычно в бинарном дереве в каждом узле поддерживают какой-нибудь инвариант. Например, «левое поддерево содержит элементы лексиграфически до текущего, правое поддерево содержит элементы лексиграфически после текущего». Тогда при обходе дерева в любой момент можно понять, куда продолжать поиск, в левое поддерево или в правое. Какой инвариант поддерживается в изображённом дереве, не понятно. Поэтому не понятно и как производить в нём поиск.

iliyap ★★★★★
()

Mad skills быдлокодинга:

void solve(int n)
{
  stack<direction> path;
  
  while (n > 0)
  {
    if (n & 1) // если n нечетное
      path.push_back(left);
    else
      path.push_back(right);

    n = (n - 1) / 2;
  }

  начать обход дерева;

  while (!path.empty())
  {
    if (path.top() == left)
    {
      идти налево по дереву;
    }
    else
    {
      идти направо;
    }

    path.pop();
  }
}

Raving_Zealot ★★
()
Ответ на: комментарий от iliyap

Инвариант таков. У элемента идентификатор N у его правой ветви N*2+1 у левой N*2+2.

Trieforce
() автор топика
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;
       how to get offset???? 
        if (aux == 1) time += climb(ID - offset, a1);
        if (aux == 2) time += climb(ID - offset, a2);
    }
    return time;
}

Тут я знаю на какую ветку выбрать у корня. После того как ветка выбрана надо представить, что она корень:

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

         to

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

offset это то значение которое превратит например 14 в 6 или 10 в 6. Для правой ветви оно в два раза больше чем для левой.

Trieforce
() автор топика

int leftchild(int n) {return n*2+1;}
int rightchild(int n) {return n*2+2;}

2 - rightchild(0)
5 - leftchild(2)
5 - leftchild(rightchild(0));

Это что ли?

Tanger ★★★★★
()

Не понятно, чего ты хочешь. Ну раз так, попробую угадать.

Если тебе надо пройти от корня до вершины с заданным номером, то ты в общем-то и сам все правильно написал. Стартуем из конечной вершины и, пока вершина не стала нулем, отнимаем 1 и делим пополам. Получилась последовательность шагов от корня к вершине в обратном порядке.

Если тебе надо пройти из одной вершины в другую, то простое решение — найти пути из этих вершин к корню и соединить по той вершине, в которой эти два пути пересекаются. Эффективное решение гуглится запросом «наименьший общий предок».

metar ★★★
()
Ответ на: комментарий от metar

> отнимаем 1 и делим пополам
Собственно, я это пишу подразумевая, что вершины у тебя пронумерованы как в полном бинарном дереве (как нарисовано в посте). Иначе бы у тебя была бы какая-то информация про то, кто там чей родитель, брал бы ее.

metar ★★★
()

У тебя изображено не бинарное дерево поиска, а сортирующее дерево. В дереве поиска в левом поддереве элементы меньше корня, в правом — больше.

anonymous
()
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; //
        offset *= aux;
        if (aux == 1) time += climb(ID - offset, a1);
        if (aux == 2) time += climb(ID - offset, a2);
    }
    return time;
}

помолюсь, авось сработает

Trieforce
() автор топика
Ответ на: комментарий от Trieforce

Корня уравнения дифференциального уравнения, блин, которое получится если выписать все числа в ряд. Решать методом Рунге-Кутты.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.