C++ 我应该使用什么样的数据结构来实现UPGMA?

C++ 我应该使用什么样的数据结构来实现UPGMA?,c++,vector,data-structures,c++14,c++17,C++,Vector,Data Structures,C++14,C++17,我要提前道歉,因为我不知道怎么问这个问题,否则我的头衔会更好 我正在努力实现这一目标。假设我有一个整数向量 std::vector<std::vector<int>> test = { {0},{1},{2},{3},{4},{5}} 这可以通过以下代码轻松实现: int x = 0; int y = 3; merge = {test[x][0],test[y][0]}; // merge is a std::vector<int> test.push_ba

我要提前道歉,因为我不知道怎么问这个问题,否则我的头衔会更好

我正在努力实现这一目标。假设我有一个整数向量

std::vector<std::vector<int>> test = { {0},{1},{2},{3},{4},{5}}
这可以通过以下代码轻松实现:

int x = 0;
int y = 3;
merge = {test[x][0],test[y][0]}; // merge is a std::vector<int>
test.push_back(merge);
test.erase(test.begin() + x)
test.erase(test.begin() + y - 1); // -1 since the first erase shifts everything over
这就是我遇到问题的地方,因为我现在似乎已经在测试的位置3引入了
std::vector
。使用
merge={test[x][0],test[y][0]}
将失败。随着时间的推移,情况会变得更糟。因为我可能有这样的东西:

test = { {1}, {2}, {4}, {5}, {0,3} }
test = { {1}, {4}, {5}, {2,{0,3} };
test = { {1}, {{4,5},{2,{0,3}}} }
我想我很快就意识到我的数据结构是错误的,但是我完全不知道我需要使用什么样的数据结构。我可以使用什么样的数据结构来轻松实现这一点


我再次为这个糟糕的问题道歉

你在这里建一棵树。最好在这里创建新节点。因此,当合并{0}和{3}时,将创建一个值为{0,3}的新节点。如果合并{2},则创建一个节点{2,0,3}

此时,您可能会反对并说您需要结构{2,{0,3}。这实际上是不需要的,而且实际上效率很低。您只需要在流程结束时使用该结构。在这一点上,您可以根据没有实际删除旧节点的事实来重建树-您只需将它们放在一边

这基本上意味着你需要第二个向量。创建{0,3}后,将{0}和{3}移动到第二个向量。创建{2,0,3}后,将{2}和{0,3}附加到第二个向量


当然,这不是最节省内存的实现。第二个向量的大小为O(N*N),因为它保留了每个中间树节点。更节省空间的实现是用一个简单的树替换第二个向量向量,其中叶节点只有一个值,而非叶节点只有两个子指针。此树只保留结构。

您正在构建一个二叉树。每个子级都是一个
int
或一个子树。这在任何东西的
向量中都是无效的

#include <vector>
#include <variant>
#include <memory>
#include <utility>

using Node = std::variant<std::shared_ptr<class Tree>, int>;

struct Tree {
    Tree(Node left, Node right) : left(left), right(right) {}
    Node left;
    Node right;
};

std::pair<std::vector<Node>::iterator, std::vector<Node>::iterator> decide_merge(const std::vector<Node> & v)
{
    // Some process to choose elements
    return { v.begin(), v.begin() + 1 };
}

int main()
{
    std::vector<Node> nodes = { {0}, {1}, {2}, {3}, {4}, {5} };
    while (nodes.size() > 1)
    {
        auto [left, right] = decide_merge(nodes);
        auto tree = std::make_shared<Tree>(*left, *right);
        nodes.erase(left);
        nodes.erase(right);
        nodes.push_back(tree);
    }
}
#包括
#包括
#包括
#包括
使用Node=std::variant;
结构树{
树(节点左,节点右):左(左),右(右){
左淋巴结;
节点权;
};
std::pair decision\u merge(const std::vector&v)
{
//选择元素的一些过程
返回{v.begin(),v.begin()+1};
}
int main()
{
向量节点={0}、{1}、{2}、{3}、{4}、{5};
while(nodes.size()>1)
{
自动[左,右]=决定合并(节点);
自动树=标准::使共享(*左,*右);
删除节点(左);
删除节点(右);
节点。推回(树);
}
}

我想我很难找出如何利用这些差异创建矩阵。该算法是直接的,我有初始差分矩阵。然而,我甚至不知道如何落实你的建议。这不需要知道向量{0,3}以某种方式存在吗?@Sailanarmo:当然存在。在迭代1之后,{0,3}在第一个向量中;在迭代2之后,它被移动到第二个向量,因为现在第一个向量包含{2,0,3},我刚刚检查了这个,但是它没有编译?我使用c++17标志运行它,但是有一个未定义的引用来决定_merge.Yes。您没有描述选择要合并的节点的机制。它在wiki上有描述。基本上,您可以根据我已经计算的距离创建一个矩阵。选择除0以外的最小数字,并将这些数字合并在一起。