C++ 树上两片叶子的最低共同祖先
我有以下树结构:C++ 树上两片叶子的最低共同祖先,c++,algorithm,tree,C++,Algorithm,Tree,我有以下树结构: struct Node { int data; Node* parent = nullptr; } 每个节点最多有一个父节点,但可以有多个子节点。我试图找到两个没有任何子节点的节点(node1和node2)的最低共同祖先 这是我当前的代码: std::vector<Node*> ancestors1; std::vector<Node*> ancestors2; temp_node = node1->parent; while(tem
struct Node {
int data;
Node* parent = nullptr;
}
每个节点最多有一个父节点,但可以有多个子节点。我试图找到两个没有任何子节点的节点(node1和node2)的最低共同祖先
这是我当前的代码:
std::vector<Node*> ancestors1;
std::vector<Node*> ancestors2;
temp_node = node1->parent;
while(temp_node!=nullptr) {
ancestors1.push_back(temp_node);
temp_node = temp_node->parent;
}
temp_node = node2->parent;
while(temp_node!=nullptr) {
ancestors2.push_back(temp_node);
temp_node = temp_node->parent;
}
Node* common_ancestor = nullptr;
if (ancestors1.size() < ancestors2.size()) {
ptrdiff_t t = ancestors1.end() - ancestors1.begin();
std::vector<Node*>::iterator it1 = ancestors1.begin();
std::vector<Node*>::iterator it2 = ancestors2.end() - t;
while(it1!=ancestors1.end()) {
if (*it1 == *it2) {
common_ancestor = *it1;
}
++it1;
}
} else {
ptrdiff_t t = ancestors2.end() - ancestors2.begin();
std::vector<Node*>::iterator it2 = ancestors2.begin();
std::vector<Node*>::iterator it1 = ancestors1.end() - t;
while(it2!=ancestors2.end()) {
if (*it1 == *it2) {
common_ancestor = *it1;
}
++it2;
}
}
return common_ancestor
std::vector ansestors1;
std::载体2;
temp_node=node1->parent;
while(临时节点!=nullptr){
取消存储1.向后推(临时节点);
临时节点=临时节点->父节点;
}
temp_node=node2->parent;
while(临时节点!=nullptr){
ancestors2.推回(临时节点);
临时节点=临时节点->父节点;
}
节点*公共_祖先=nullptr;
如果(ancestors1.size()
这段代码并不总是有效,我不知道为什么。我发现了问题。除了需要移动两个迭代器而不是一个迭代器(感谢Jarod42和v78),我还需要在找到最低的公共祖先(否则它将返回最高的公共祖先)后立即跳出while循环
对不起,我无法抗拒 除了打字错误和bug,我相信它看起来更简单:
#include <cassert>
#include <algorithm>
#include <iostream>
#include <vector>
struct Node {
int data;
Node *parent = nullptr;
};
Node* findCommonAncestor(Node *pNode1, Node *pNode2)
{
// find paths of pNode1 and pNode2
std::vector<Node*> path1, path2;
for (; pNode1; pNode1 = pNode1->parent) path1.push_back(pNode1);
for (; pNode2; pNode2 = pNode2->parent) path2.push_back(pNode2);
// revert paths to make indexing simple
std::reverse(path1.begin(), path1.end());
std::reverse(path2.begin(), path2.end());
// compare paths
Node *pNode = nullptr; // ancestor
size_t n = std::min(path1.size(), path2.size());
for (size_t i = 0; i < n; ++i) {
if (path1[i] == path2[i]) pNode = path1[i];
else break;
}
// done
return pNode;
}
int main()
{
// sample tree:
/* 1
* |
* 2
* / \
* 3 4
* |
* 5
*/
Node node1 = { 1, nullptr };
Node node2 = { 2, &node1 };
Node node3 = { 3, &node2 };
Node node4 = { 4, &node2 };
Node node5 = { 5, &node4 };
Node *pNode = findCommonAncestor(&node3, &node5);
if (pNode) {
std::cout << "Lowest common ancestor: " << pNode->data << '\n';
} else {
std::cout << "No common ancestor found!\n";
}
}
注意:
而迭代器的使用有助于保持代码的通用性
我会考虑这样一个例子:坚持旧数组(AK<代码> STD::向量< /代码>)索引简化了事情。
< P>你不应该需要额外的空间来解决这个问题:
// measure depths
size_t depth1=0;
for (Node *n = node1; n; n=n->parent, ++depth1);
size_t depth2=0;
for (Node *n = node2; n; n=n->parent, ++depth2);
// move the deeper one up until they're the same depth
for (;depth1 > depth2; node1 = node1->parent, --depth1);
for (;depth2 > depth1; node2 = node2->parent, --depth2);
// move them both up until they match
while(node1 != node2) {
node1 = node1->parent;
node2 = node2->parent;
}
return node1;
请尝试创建最小且最简单的“不总是有效”树,并使用调试器逐步检查代码以帮助找出问题所在。创建函数以列出祖先,而不是重复逻辑。顺便说一句,当您将node2
的祖先放在antestors1
中时,只有一个迭代器移动,所以您只需检查一个祖先。只需执行++it1++it2代码>在if-else块的两侧。it2=ancestors2.end()-t
-为什么?两个路径都必须从根开始。难道你不能从一开始就迭代这两条路径,一旦它们不同就立即中断吗?实际上要简单得多。谢谢
// measure depths
size_t depth1=0;
for (Node *n = node1; n; n=n->parent, ++depth1);
size_t depth2=0;
for (Node *n = node2; n; n=n->parent, ++depth2);
// move the deeper one up until they're the same depth
for (;depth1 > depth2; node1 = node1->parent, --depth1);
for (;depth2 > depth1; node2 = node2->parent, --depth2);
// move them both up until they match
while(node1 != node2) {
node1 = node1->parent;
node2 = node2->parent;
}
return node1;