бинарное дерево -print элементов в соответствии с уровнем

голоса
6

Этот вопрос был задан мне в интервью:

бинарное

позволяет сказать, что мы имеем выше бинарного дерева, как я могу производить вывод, как показано ниже

2 7 5 2 6 9 5 11 4

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

кто-нибудь может дать anyidea, как мы можем достичь этого?

Задан 14/04/2011 в 08:07
источник пользователем
На других языках...                            


7 ответов

голоса
2

Обход в вашем вопросе называется level-order traversalи это то , как это делается (очень простой / чистый фрагмент кода я нашел).

Вы в основном использовать очереди и порядок операций будет выглядеть примерно так:

enqueue F
dequeue F
enqueue B G
dequeue B
enqueue A D
dequeue G
enqueue I
dequeue A
dequeue D
enqueue C E
dequeue I
enqueue H
dequeue C
dequeue E
dequeue H

Для этого дерева (прямо из Википедии):
введите описание изображения здесь

Ответил 14/04/2011 в 08:14
источник пользователем

голоса
2

Термин для этого является уровень порядка обхода . Википедия описывает алгоритм , который с помощью очереди :

levelorder(root) 
  q = empty queue
  q.enqueue(root)
  while not q.empty do
    node := q.dequeue()
    visit(node)
    if node.left ≠ null
      q.enqueue(node.left)
    if node.right ≠ null
      q.enqueue(node.right)
Ответил 14/04/2011 в 08:14
источник пользователем

голоса
2

BFS :

std::queue<Node const *> q;
q.push(&root);
while (!q.empty()) {
    Node const *n = q.front();
    q.pop();
    std::cout << n->data << std::endl;
    if (n->left)
        q.push(n->left);
    if (n->right)
        q.push(n->right);
}

Итерационное Углубление также будет работать и экономит использование памяти, но за счет времени вычисления.

Ответил 14/04/2011 в 08:16
источник пользователем

голоса
6

Вы должны сделать ширину первого обхода дерева. Здесь она описывается следующим образом :

Ширина-первых обходом: Глубина-первых, это не единственный способ пройти через элементы дерева. Другой способ, чтобы пройти через них уровень-на-уровне.

Например, каждый элемент существует на определенном уровне (или глубины) в дереве:

    tree
      ----
       j         <-- level 0
     /   \
    f      k     <-- level 1
  /   \      \
 a     h      z  <-- level 2
  \
   d             <-- level 3

Такие люди, как количество вещей, начиная с 0.)

Таким образом, если мы хотим посетить элементы уровень-на-уровень (и слева направо, как обычно), мы начнем на уровне 0 с J, а затем перейти на уровень 1 для е и к, а затем перейти на уровень 2 для, Н и г, и, наконец, перейти на уровень 3 для г.

Этот уровень, по-уровне обхода называется ширину первого обхода, потому что мы исследуем широту, то есть всю ширину дерева на заданном уровне, прежде чем глубже.

Ответил 14/04/2011 в 08:16
источник пользователем

голоса
0

Я хотел бы использовать коллекцию, например std::list, для хранения всех элементов текущего изображения уровня:

  1. Собирают указатели на все узлы на текущем уровне в контейнере
  2. Печать узлов, перечисленных в контейнере
  3. Создайте новый контейнер, добавьте подузлы всех узлов в контейнере
  4. Переписать старый контейнер с новым контейнером
  5. повторять до тех пор, пока контейнер не пуст
Ответил 14/04/2011 в 08:18
источник пользователем

голоса
0

В качестве примера того, что вы можете сделать на одном из интервью, если вы не помните / не знаете «официальный» алгоритма, моя первая мысль была - траверс дерева в регулярном предзаказе тащит счетчик уровня вдоль, сохраняя вектор связанных списков указателей на узлы на уровне, например,

levels[level].push_back(&node);

и в конце печати списка каждого уровня.

Ответил 14/04/2011 в 08:39
источник пользователем

голоса
2

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

Теперь только проблема заключается в том, чтобы проверить, если мы находимся на последний элемент на любом уровне. По этой причине, мы должны быть присоединяя разделитель (NULL в данном случае), чтобы отметить конец уровня.

Алгоритм: 1. Положите корень в очереди.
2. Put NULL в очереди.
3. В то время как очередь не пуста
4. х = первый элемент выборка из очереди
5. Если й не NULL
6. х-> rpeer <= верхний элемента очереди.
7. положить левый и правый дочерний х в очереди
8. еще
9. Если очередь не пуста
10. положить NULL в очереди
11. Конец если
12. конец , а
13. вернуться

#include <queue>

void print(tree* root)
{
  queue<tree*> que;
  if (!root)
      return;

  tree *tmp, *l, *r;
  que.push(root);
  que.push(NULL);

  while( !que.empty() )
  {
      tmp = que.front();
      que.pop();
      if(tmp != NULL)
      {
          cout << tmp=>val;  //print value
          l = tmp->left;
          r = tmp->right;
          if(l) que.push(l);
          if(r) que.push(r);
      }
      else
      {
          if (!que.empty())
              que.push(NULL);
      }
  }
  return;
}
Ответил 14/04/2011 в 11:55
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more