如何在 C 中实现多分支树结构
Posted
技术标签:
【中文标题】如何在 C 中实现多分支树结构【英文标题】:How to implement a multibranch tree structure in C 【发布时间】:2011-08-27 13:14:14 【问题描述】:我很久没有用 C 写代码了。 我正在尝试做一棵多叶树。我正在尝试将 C# trie 实现转换为 C,以便使用 CUDA 在 GPU 上运行它。但我一直坚持这一点。你能帮我吗?
我的节点实现如下:
struct Node2
char *Key;
char *ConsAlterKey;
char *MasterKey;
bool VowelDeletion;
char *Data;
char *MasterData;
Node2 *Childs;
int ChildCount;
;
这是我将节点添加到 trie 的函数:
void AddAsChildren2(Node2 *Trie,int count)
//Trie->Childs=new Node2[count];
Trie->Childs=(Node2 *)malloc(sizeof(Node2)*count);
for(int i=0;i<count;i++)
Trie->Childs[i].Key= GetKey();
Trie->Childs[i].ConsAlterKey=GetConsAlterKey();
Trie->Childs[i].MasterKey=GetMasterKey();
Trie->Childs[i].VowelDeletion=GetVowelDeletion();
Trie->Childs[i].Data=GetData();
Trie->Childs[i].MasterData=GetMasterData();
Trie->Childs[i].ChildCount=GetChildCount();
if(Trie->Childs[i].ChildCount> 0)
AddAsChildren2(&(Trie->Childs[i]),Trie->Childs[i].ChildCount);
我在主函数中这样称呼它:
Node2 NodeNew;
.
.
.
AddAsChildren2(&NodeNew,NodeNew->ChildCount);
TraverseTree2(&NodeNew);
但是当我尝试遍历树时,我会得到错误的值,有时还会出现异常。(可能是子节点的内存分配问题)
我在这里做错了什么?
Ps:第一个节点有子节点,我没有分配值的问题,所以忽略“getter”函数。我已经更改了它们以简化代码。我的问题是代码完成这部分后我丢失了值。
感谢您的快速响应。我从文件中读取值。
文件的结构是这样的。
如果一行/项目没有子节点,则以“>”结尾,否则以 ChildCount 值结尾。这里“-”字符表示 NULL 值。
< root - - - - - 2
< a - - False - - 4
< aö - - False 184 - >
< dfı - - False 188 - >
< et ed - False 189 - 3
< aö - - False 184 - >
< dfı - - False 188 - >
< k ğ - False 191 - >
>
< k ğ - False 191 - >
>
< a - - False - - 4
< aö - - False 184 - >
< dfı - - False 188 - >
< et ed - False 189 - 3
< aö - - False 184 - >
< dfı - - False 188 - >
< k ğ - False 191 - >
>
< k ğ - False 191 - >
>
>
而不是我的代码的简化版本如下:
void AddAsChildren2(Node2 *Trie,FILE *fp,int count)
char string[50];
char *line=NULL;
char *Temp;
Trie->Childs=(Node2 *)malloc(sizeof(Node2)*count);
//Trie->Childs=new Node2[count];
for(int i=0;i<count;i++)
if(fgets(string,50,fp))
line=strtok(string," ");
if(strcmp (line,"<")==0)
line=strtok( NULL, " ");
Trie->Childs[i].Key= (strcmp(line,"-")==0?"":line);
line=strtok( NULL, " ");
Trie->Childs[i].ConsAlterKey=(strcmp(line,"-")==0?"":line);
line=strtok( NULL, " ");
Trie->Childs[i].MasterKey=(strcmp(line,"-")==0?"":line);
line=strtok( NULL, " ");
Trie->Childs[i].VowelDeletion=(strcmp(line,"-")==0?"":line);
line=strtok( NULL, " ");
Trie->Childs[i].Data=(strcmp(line,"-")==0?"":line);
line=strtok( NULL, " ");
Trie->Childs[i].MasterData=(strcmp(line,"-")==0?"":line);
Temp = strtok( NULL, " ");
if(strcmp(Temp,">")==0)
//ends with >
Trie->Childs[i].ChildCount=0;
else if((strcmp(Temp,"\n")!=0)&&(strlen(Temp)> 0))
//ends with childcount value so it have childs
Trie->Childs[i].ChildCount=atoi(Temp);
AddAsChildren2(&(Trie->Childs[i]),fp,Trie->Childs[i].ChildCount);
遍历函数如下:
void traversetree2(Node2 *tree)
printf("Key %s\n",tree->Key);
printf("ConsAlterKey %s\n",tree->ConsAlterKey);
printf("MasterKey %s\n",tree->MasterKey);
printf("Data %s\n",tree->Data);
printf("MasterData %s\n",tree->MasterData);
if(tree->ChildCount>0)
for(int i=0;i<tree->ChildCount;i++)
traversetree2(&(tree->Childs[i]));
输出是:
Key root
ConsAlterKey
MasterKey
Data
MasterData
Key ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
ConsAlterKey
MasterKey
Data
MasterData
Key ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░÷E
ConsAlterKey
MasterKey
Data ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░÷E
MasterData
Key ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░÷E
ConsAlterKey
MasterKey
Data ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░÷E
MasterData
Key ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░÷E
ConsAlterKey ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░÷E
MasterKey
Data ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░÷E
MasterData
Key ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠§E
ConsAlterKey
MasterKey
Data ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠§E
MasterData
Key ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠§E
ConsAlterKey
MasterKey
Data ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠§E
MasterData
Key ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠§E
ConsAlterKey ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠§E
MasterKey
Data ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠§E
MasterData
【问题讨论】:
我认为您显示的代码没有任何问题。您是否也在某个时候释放了尝试?你能显示回溯吗? 【参考方案1】:啊,使用更多代码很容易:您的问题是char string[50]
是一个局部变量,并且您将许多指针保存到该局部数组中,当AddAsChildren2
返回时这些指针会丢失。根据您是否需要释放此结构,您可以strdup()
整行然后从中保存令牌或strdup()
每个单独的令牌(以简化释放)。
【讨论】:
非常感谢;我不能说我是多么感激它。你为我节省了几个小时。 请原谅我的新手问题,但我还有一个问题要问你。我已将Trie->Childs[i].Key= (strcmp(line,"-")==0?"":line)
更改为Trie->Childs[i].Key= (strcmp(line,"-")==0?"":**strdup(line)**)
。像这样将这些值分配给节点的属性后,我应该立即释放它们吗?我的意思是我应该在每次分配后使用LocalFree(line)
吗?
不,strdup(line)
就可以了。如果您想释放 整个 结构,挑战就来了。你不能释放你的文字 ""
字符串。最好使用strdup( cond ? "" : line )
,以便分配每个字符串,如果你曾经处理过整个 Trie,你可以free(Trie->Childs[i].Key)
。以上是关于如何在 C 中实现多分支树结构的主要内容,如果未能解决你的问题,请参考以下文章