C++ 将n元树表示为向量并遍历
我已经实现了一个n元树(更具体地说,是trie),我想知道是否有一种方法可以将它表示为向量并遍历它。对于二叉树,这将是微不足道的(请参阅),但我似乎找不到一种方法来对n元树执行此操作。 我的最终目标是将矢量表示的树存储到一个文件中,对其进行mmap并执行快速查找,而无需将其有效加载到内存中。C++ 将n元树表示为向量并遍历,c++,algorithm,vector,tree,trie,C++,Algorithm,Vector,Tree,Trie,我已经实现了一个n元树(更具体地说,是trie),我想知道是否有一种方法可以将它表示为向量并遍历它。对于二叉树,这将是微不足道的(请参阅),但我似乎找不到一种方法来对n元树执行此操作。 我的最终目标是将矢量表示的树存储到一个文件中,对其进行mmap并执行快速查找,而无需将其有效加载到内存中。 将trie与mmap-ped指针一起使用,而不是分配其内部结构,将trie存储在磁盘ad上的一种有效方法也将非常有用 谢谢。任何图形结构都可以表示为节点的平面数组(事实上,计算机内存就是这样工作的)。您只需
将trie与mmap-ped指针一起使用,而不是分配其内部结构,将trie存储在磁盘ad上的一种有效方法也将非常有用
谢谢。任何图形结构都可以表示为节点的平面数组(事实上,计算机内存就是这样工作的)。您只需要使用索引而不是指针,因为当
向量增长或结构为mmap
'd时,指针将无效
这是一个三向树,作为平面向量:
struct Node {
Node(int data) : payload(data)
{
for (int i = 0; i < 3; i++) {
child[i] = (size_t)(-1); // invalid
}
}
int payload;
size_t child[3];
};
typedef std::vector<Node> Tree;
void add_node(Tree &t, size_t parent, int child_index, int payload)
{
t.push_back(Node(payload));
t[parent].child[child_index] = t.size() - 1;
}
变成
t[t[node_idx].child[1]]
等。即,每个节点的查找都通过树
对象。如果有一棵树,其中每个节点n正好有k个子节点,则可以将节点n的子节点放置在数组中的k*n+m位置,其中m介于0和k-1之间。如果每个节点都有k个或更少的子节点,这也会起作用,但是如果很多节点的子节点少于k个,那么它将使用比所需内存多得多的内存。我所知道的将树存储为数组(其中节点具有不同数量的子节点)的唯一其他方法是存储辅助数组,,其中,对于每个节点,将偏移量存储到原始数组中以查找该节点的子节点,然后还可以存储每个节点的子节点数,或者只需查找下一个节点的子节点的偏移量,以确定该节点的子节点数 假设您知道树的节点号
您可以将adj向量的大小更改为合适的值
代码->
#include<iostream>
#include<vector>
using namespace std;
vector<int> adj[100000000];
void dfs(int);
int main()
{
int i,n,root,par;
cin>>n;
//Input line contains n space separated integers.
// The ith integer represents the immediate ancestor of the ith node
// Node having 0 as parent node is the Root Node
i=1;
while(i<=n)
{
cin>>par;
if(par==0)
{
root=i;
}
else
{
adj[par].push_back(i);
}
i++;
}
//traversal of the Tree(Inorder traversal)
dfs(root);
}
void dfs(int at)
{
vector<int>::iterator it;
it=adj[at].begin();
cout<<*it<<" ";
while(it!=adj[at].end())
{
dfs((*it));
it++;
}
return;
}
#包括
#包括
使用名称空间std;
向量调整[100000000];
无效dfs(int);
int main()
{
int i,n,root,PAR;
cin>>n;
//输入行包含n个空格分隔的整数。
//第i个整数表示第i个节点的直接祖先
//将0作为父节点的节点是根节点
i=1;
而(i>par;
如果(par==0)
{
根=i;
}
其他的
{
形容词[par]。推回(i);
}
i++;
}
//树的遍历(按顺序遍历)
dfs(根);
}
无效dfs(int at)
{
向量::迭代器;
it=adj[at].begin();
在你的例子中,你有一个固定数量的子节点(3),如果每个节点都有一个可变数量的子节点(例如一个trie)会怎么样?如果你应该序列化每个节点,如果中间有B和C,并且它们的大小不是固定的(因为它们可以有任意数量的子节点),你怎么能从节点a“跳”到节点D?@SimoneMargaritelli在trie中,您有固定数量的子项、字母表的元素,或者如果您规定所有输入都是字节字符串,则只有256个(对于压缩,您实际上可以将它们视为半字节字符串,存储16个子项,并将节点数增加一倍)template
-将这些结构化为template struct Node{…
@larsmans是的,标准实现是使用Node*子节点[256]
但是我使用一个链表,在需要时增加它,每个节点都是一个struct{uint8_t值;void*数据;ll_t子节点;}
…使用的内存更少:)@SimoneMargaritelli在正常情况下,是的。也许你应该看看压缩方案。正是我想到的,只需保留偏移量并将其用作指向文件中jmp访问的节点指针,但这似乎是一个缓慢的解决方案,所以我问:)
#include<iostream>
#include<vector>
using namespace std;
vector<int> adj[100000000];
void dfs(int);
int main()
{
int i,n,root,par;
cin>>n;
//Input line contains n space separated integers.
// The ith integer represents the immediate ancestor of the ith node
// Node having 0 as parent node is the Root Node
i=1;
while(i<=n)
{
cin>>par;
if(par==0)
{
root=i;
}
else
{
adj[par].push_back(i);
}
i++;
}
//traversal of the Tree(Inorder traversal)
dfs(root);
}
void dfs(int at)
{
vector<int>::iterator it;
it=adj[at].begin();
cout<<*it<<" ";
while(it!=adj[at].end())
{
dfs((*it));
it++;
}
return;
}