Как найти самого низкого общего предка двух узлов в каком-либо двоичном дереве?

Я лично нашел GLPK лучше (т.е. быстрее), чем LP_SOLVE. Это поддерживает различные форматы файлов, и дальнейшим преимуществом является свой интерфейс библиотеки, который позволяет беспрепятственную интеграцию с Вашим приложением.

183
задан Glorfindel 26 April 2019 в 12:04
поделиться

5 ответов

Ник Джонсон прав в том, что алгоритм временной сложности O (n) - лучшее, что вы можете сделать, если у вас нет родительских указателей.) Для простой рекурсивной версии этого алгоритма см. Код в Сообщение Киндинга , которое выполняется за время O (n).

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

Итак, для 8 в вашем примере вы получите (показаны шаги): {4}, { 2, 4}, {1, 2, 4}

Сделайте то же самое для другого рассматриваемого узла, в результате (шаги не показаны): {1, 2}

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

Этот алгоритм требует времени O (h), где h - высота дерева. В худшем случае O (h) эквивалентно O (n), но если дерево сбалансировано, это только O (log (n)). Также требуется пространство O (h). Возможна улучшенная версия, которая использует только постоянное пространство, с кодом, показанным в сообщении CEGRD


. Независимо от того, как построено дерево, если это будет операция, которую вы выполняете с деревом много раз, не меняя ее между ними, вы можете использовать другие алгоритмы, которые требуют подготовки O (n) [линейного] времени, но тогда поиск любой пары занимает только O (1) [постоянное] время. Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)

В худшем случае O (h) эквивалентно O (n), но если дерево сбалансировано, это только O (log (n)). Также требуется пространство O (h). Возможна улучшенная версия, которая использует только постоянное пространство, с кодом, показанным в сообщении CEGRD


. Независимо от того, как построено дерево, если это будет операция, которую вы выполняете с деревом много раз, не меняя ее между ними, вы можете использовать другие алгоритмы, которые требуют подготовки O (n) [линейного] времени, но тогда поиск любой пары занимает только O (1) [постоянное] время. Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)

В худшем случае O (h) эквивалентно O (n), но если дерево сбалансировано, то это только O (log (n)). Также требуется пространство O (h). Возможна улучшенная версия, которая использует только постоянное пространство, с кодом, показанным в сообщении CEGRD


. Независимо от того, как построено дерево, если это будет операция, которую вы выполняете с деревом много раз, не меняя ее между ними, вы можете использовать другие алгоритмы, которые требуют подготовки O (n) [линейного] времени, но тогда поиск любой пары занимает только O (1) [постоянное] время. Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)

с кодом, показанным в сообщении CEGRD


. Независимо от того, как построено дерево, если это будет операция, которую вы выполняете с деревом много раз, не меняя ее между ними, вы можете использовать другие алгоритмы, требующие O ( n) подготовка по [линейному] времени, но тогда поиск любой пары занимает всего O (1) [постоянное] время. Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)

с кодом, показанным в сообщении CEGRD


. Независимо от того, как построено дерево, если это будет операция, которую вы выполняете с деревом много раз, не меняя ее между ними, вы можете использовать другие алгоритмы, требующие O ( n) подготовка по [линейному] времени, но тогда поиск любой пары занимает всего O (1) [постоянное] время. Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)

Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)

Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)

70
ответ дан 23 November 2019 в 06:01
поделиться

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

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

7
ответ дан 23 November 2019 в 06:01
поделиться

Автономный алгоритм наименее общих предков Тарьяна достаточно хорош (см. также Википедия ). Более подробная информация о проблеме (проблема с наименьшим общим предком) содержится в Википедии .

5
ответ дан 23 November 2019 в 06:01
поделиться

Я сделал попытку с иллюстративными изображениями и рабочим кодом на Java,

http://tech.bragboy.com/2010/ 02 / наименьший-общий-предок-без-using.html

3
ответ дан 23 November 2019 в 06:01
поделиться

Это можно найти по адресу:-. http://goursaha.freeoda.com/DataStructure/LowestCommonAncestor.html

 tree_node_type *LowestCommonAncestor(
 tree_node_type *root , tree_node_type *p , tree_node_type *q)
 {
     tree_node_type *l , *r , *temp;
     if(root==NULL)
     {
        return NULL;
     }

    if(root->left==p || root->left==q || root->right ==p || root->right ==q)
    {
        return root;
    }
    else
    {
        l=LowestCommonAncestor(root->left , p , q);
        r=LowestCommonAncestor(root->right , p, q);

        if(l!=NULL && r!=NULL)
        {
            return root;
        }
        else
        {
        temp = (l!=NULL)?l:r;
        return temp;
        }
    }
}
7
ответ дан 23 November 2019 в 06:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: