我有一个类似于以下内容的文本文件:
person: head, body
head: eyes, nose, ears, mouth
body: arm, leg
arm: elbow, hand
leg: thigh, knee, foot
我试图用邻接表或有向图来表示它。最好的方法是什么?我想不出最好的数据结构或如何在 C++ 中表示它。
我已经尝试使用一个结构,其键值(person、head 等)和它的父索引,它的子元素作为 vector :
struct Node
{
string key;
int parentIndex;
vector<string> children;
};
但这似乎效率不高。有什么想法吗?
也许这样会更好?
struct {
string key;
Node* parent;
vector<Node> children;
};
您的数据样本中有几个问题尚未得到解答:是否始终只有一个入口点(例如:人)?它总是自上而下的分解(即每个元素最多有一个父元素)吗?元素是否总是以正确的方式出现:首先是顶部,然后是底部?
如果所有三个问题的答案都是肯定的,那么您建议的结构是合适的:
- 如果始终从顶部开始探索,就足够有效了。
- 查找特定节点将非常耗时,因为您必须遍历整个结构。
还有几点需要修正:
- 复制一个节点会很棘手(因为指向父节点的指针必须针对复制的节点以及它的子节点和子节点的子节点进行更改。
- 向数组添加元素可能会使所有子项和子项的子项的父指针无效。
如您所见,最佳数据结构不仅取决于内容,还取决于您将如何使用它。
有很多其他方法可以做到这一点,以不同的方式平衡性能方面。例如:
class mygraph {
struct node { // nodes that you read:
string name;
int id; // index of the node in the nodes vector
vector<int> in; // parent(s) that can lead to this node
vector<int> out; // children you can go to
};
vector<node> nodes; // all the nodes in arbitrary sequential order
map<string, int> dict; // map converting the names into ids (redundant and optional, useful for efficien search by name);
public:
// members to populate the structure and to acces the nodes cleanly.
};
优点:
- 通过 id 查找任何节点都非常快,因为它只是索引一个数组。
- 您不必担心结构的复制,因为没有指针。
- 由于输入/输出 vector ,您可以从您想要的任何节点快速向前或向后移动。
- 冗余映射(即索引和名称)加速按名称搜索节点
不便之处:填充结构时有一些开销:您需要通过验证映射中的名称将每个名称转换为 ID,如果不存在,则在节点 vector 中创建一个新节点并在映射中插入名称+新 ID。