Я лично нашел GLPK лучше (т.е. быстрее), чем LP_SOLVE. Это поддерживает различные форматы файлов, и дальнейшим преимуществом является свой интерфейс библиотеки, который позволяет беспрепятственную интеграцию с Вашим приложением.
Ник Джонсон прав в том, что алгоритм временной сложности 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) [постоянное] время. Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)
Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки) Ссылки на эти алгоритмы можно найти на странице с наименьшей проблемой общего предка в Википедии . (Благодарим Джейсона за первоначальное размещение этой ссылки)Ну, это зависит от структуры вашего двоичного дерева. Предположительно у вас есть способ найти желаемый листовой узел с учетом корня дерева - просто примените его к обоим значениям, пока выбранные вами ветви не расходятся.
Если у вас нет способа найти желаемый лист с учетом корня , то ваше единственное решение - как при нормальной работе, так и для поиска последнего общего узла - это поиск дерева методом перебора.
Автономный алгоритм наименее общих предков Тарьяна достаточно хорош (см. также Википедия ). Более подробная информация о проблеме (проблема с наименьшим общим предком) содержится в Википедии .
Я сделал попытку с иллюстративными изображениями и рабочим кодом на Java,
http://tech.bragboy.com/2010/ 02 / наименьший-общий-предок-без-using.html
Это можно найти по адресу:-. 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;
}
}
}