Обход дерева

Тема в разделе "WASM.A&O", создана пользователем Mika0x65, 19 авг 2007.

  1. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Я наконец понял что написал попробую теперь другим обяснить 8)

    Когда в некоторый узел мы приходим сверху:
    from == parent
    cur == (left,right)

    Эти указатели переставляются местами:
    from == left
    cur == (right,parent)
    и дальше обменивая from и cur мы начинаем обходить левое поддерево, при возврате из левого поддерева картина будет точно такая же.

    Еще раз переставляем указатели:
    from == right
    cur == (parent,left)
    обмениваем from и cur и обходим правое подерево.

    И еще раз переставляем указатели:
    from == parent
    cur == (left,right)
    и обменивая from и cur возвращаемся к родительскому узлу

    Маркер END нужен для того чтобы определить момент окончания обхода, поскольку у корня нет родителя. Чтобы исключить обработку каждого узла по нескольку раз производится проверка что from > cur->left и cur->right. При этом END и адрес любого узла дерева должны быть больше чем NULL.
     
  2. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.243
    Black_mirror
    насчёт окончания обхода дерева: лучше хранить общее колво ветвей, так как это поволяет избежать лишних проблем. и, далеко не в каждом дереве, все ветви не NULL.
     
  3. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    UbIvItS
    А если нам попалось дерево про которое мы не знаем сколько в нём ветвей?
    Про NULL я ничего не сказал в описании, но алгоритм его успешно обрабатывает, посмотри внутренний цикл.
     
  4. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.243
    Black_mirror
    это не страшно - алгос должен пройти A ветвей в корне, тогда он заканчивает свою работу.
    я б релизил такой алгос через счётчик, а каждый узел должен содержать ссылку на ближайшего родителя, тогда можно организовать наиболее оптимальный обход.
     
  5. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    UbIvItS
    Алгоритм в студию! А то мы еще долго друг друга не поймём.
     
  6. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Тем временем, знакомый предложил проверять, в каком поддереве мы находимся, сравнивая текущий указатель с указателем right родителя текущего узла. Признак в таком случае не нужен. В итоге получилось примерно так:
    Код (Text):
    1. NODE *ptr = &n1;
    2.  
    3. while(1)
    4. {
    5.  
    6.     if (ptr ->left)
    7.     {
    8.         ptr = ptr ->left;
    9.     }
    10.     else
    11.     {
    12.         while (ptr ->parent && ptr == ptr ->parent ->right)
    13.             ptr = ptr ->parent;
    14.  
    15.         if (ptr ->parent == NULL)
    16.             break;
    17.  
    18.         ptr = ptr ->parent ->right;
    19.     }
    20. }
     
  7. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Mika0x65
    Этот алгоритм упадёт при возврате из левого поддерева если правое отсутствует, на строке:
    ptr = ptr ->parent ->right;
     
  8. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    Mika0x65

    Угу, именно это я и имел в виду в самом начале: постоянный порядок (здесь левый-правый) и определено сравнение (здесь по адресу).

    Black_mirror
    Почему упадет, parent ведь проверяется на существование: while (ptr ->parent ...
     
  9. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Stiver
    Действительно, на этой строке не упадёт, тут ptr просто станет равен NULL, а упадёт на проверке условия if(ptr ->left) при следующей итерации.
     
  10. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    Black_mirror

    Можно добавить while (ptr ->parent && (ptr ->parent ->right == NULL || ptr == ptr ->parent ->right)). Но это уже мелочи..
     
  11. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.243
    :)) - какое может быть сравнение адресов - попытка реализации дерева через массив убивает все плюсы этой СД: узлы создаються динамично в нормальной реализации..... а насчёт: "алгос в студию" ====> я уже всё сказал, подумайте пока сами, а если не поймёте - тогда настрокаю....
     
  12. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    UbIvItS
    Алгоритм который привёл Mika0x65 на этой странице после небольших исправлений сделанных Stiver'ом может обойти любое бинарное дерево в узлах которого есть ссылка на предка, тому алгоритму что привёл я ссылка на предка не нужна, но он в процессе работы перестраивает дерево. Оба этих алгоритма можно модифицировать так, что они смогут обходить не только бинарные деревья, причём без всякой рекурсии или самодельных стеков. А вот где ты увидел в них массивы, и почему ты предполагаешь что на нижнем уровне дерева A^k узлов я не понимаю.
     
  13. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.243
    Black_mirror
    мне непонятно как идёт в этом алгосе переход на ветки соседних узлов.
    считай, на примере бин. дерева: корень порождает две ветки; каждая ещё по две итд. =============> 2^k (k-высота дерева), таким образом счётчик позволяет задать обход дерева.
    цитата Stiver

    узлы разбросанны по неупорядоченным адресам!!