C Trie的麻烦
所以,我试图阅读一个Trie,对我来说是一个相对较新的数据结构。在我读过的地方,trie中的每个节点都由一个整数变量组成,该变量将标记一个单词的结尾,还将由26个指针组成,每个指针指向较低级别的节点(假设单词只包含小写字母字符) 现在我面临的问题是,无论我在哪里看到/阅读实现,它们都会用一个字符标记节点。就像在这种情况下: 但就我理解崔的方式而言,我相信每一条边都应该被标记为一个字符。尽管如此,我知道我们没有用于边缘的数据结构,只是用于节点。但是标记边缘不是更正确吗 另外,这是我实现insert的算法。如果你发现有什么问题,请告诉我C Trie的麻烦,c,trie,C,Trie,所以,我试图阅读一个Trie,对我来说是一个相对较新的数据结构。在我读过的地方,trie中的每个节点都由一个整数变量组成,该变量将标记一个单词的结尾,还将由26个指针组成,每个指针指向较低级别的节点(假设单词只包含小写字母字符) 现在我面临的问题是,无论我在哪里看到/阅读实现,它们都会用一个字符标记节点。就像在这种情况下: 但就我理解崔的方式而言,我相信每一条边都应该被标记为一个字符。尽管如此,我知道我们没有用于边缘的数据结构,只是用于节点。但是标记边缘不是更正确吗 另外,这是我实现inser
struct trie
{
int val;
trie* aplha[26];
}
trie* insert (trie *root, char *inp)
{
if (*input == '\0')
return root;
if (root == NULL)
{
root = (trie *) malloc(sizeof(trie));
int i = 0;
for (i=0;i<26;i++)
root->alpha[i] = NULL;
}
temp = *input - 'a';
root->alpha[temp] = insert (root->alpha[temp],input+1);
if (*(input+1)=='\0')
root->val = 1;
return root;
}
struct-trie
{
int-val;
trie*aplha[26];
}
trie*insert(trie*root,char*inp)
{
如果(*输入=='\0')
返回根;
if(root==NULL)
{
根=(trie*)malloc(sizeof(trie));
int i=0;
对于(i=0;ialpha[i]=NULL;
}
温度=*输入-‘a’;
root->alpha[temp]=插入(root->alpha[temp],输入+1);
如果(*(输入+1)='\0')
根->值=1;
返回根;
}
我很难理解如何实现删除。如果可以,请帮助我实现一个删除算法。这里有一个小程序,展示了一种实现方法。不过,在错误处理方面没有投入太多精力: <> p>我略过编辑了您的TrIEIX插入函数,并在这里显示了TyeILDEX函数。如果使用C++, >,在代码中可以将“<代码>结构VEC < /代码>改为<代码> STD::vector < /代码>。
struct trie *trie_insert(struct trie *root, char *input)
{
int idx;
if (!input) {
return root;
}
if (root == NULL) {
root = (struct trie *)calloc(1, sizeof(struct trie));
}
if (*input == '\0') {
// leaves have root->val set to 1
root->val = 1;
} else {
// carry on insertion
idx = *input - 'a';
root->alpha[idx] = trie_insert(root->alpha[idx], input+1);
}
return root;
}
struct trie *trie_delete(struct trie *root, char *s)
{
int i, idx, reap = 0;
if (!root || !s) {
return root;
}
if (!*s && root->val) {
// delete this string, and mark node as deletable
root->val = 0;
reap = 1;
} else {
// more characters to insert, carry on
idx = *s - 'a';
if (root->alpha[idx]) {
root->alpha[idx] = trie_delete(root->alpha[idx], s+1);
if (!root->alpha[idx]) {
// child node deleted, set reap = 1
reap = 1;
}
}
}
// We can delete this if both:
// 1. reap is set to 1, which is only possible if either:
// a. we are now at the end of the string and root->val used
// to be 1, but is now set to 0
// b. the child node has been deleted
// 2. The string ending at the current node is not inside the trie,
// so root->val = 0
if (reap && !root->val) {
for (i = 0; i < NRALPHA; i++) {
if (root->alpha[i]) {
reap = 0;
break;
}
}
// no more children, delete this node
if (reap) {
trie_free(root);
root = NULL;
}
}
return root;
}
struct-trie*trie\u插入(struct-trie*root,char*input)
{
int-idx;
如果(!输入){
返回根;
}
if(root==NULL){
root=(struct trie*)calloc(1,sizeof(struct trie));
}
如果(*输入=='\0'){
//叶子的根->值设置为1
根->值=1;
}否则{
//进行插入
idx=*输入-‘a’;
root->alpha[idx]=trie_insert(root->alpha[idx],输入+1);
}
返回根;
}
结构trie*trie\u delete(结构trie*root,char*s)
{
int i,idx,reaw=0;
如果(!root | |!s){
返回根;
}
如果(!*s&&root->val){
//删除此字符串,并将节点标记为可删除
根->值=0;
收获=1;
}否则{
//要插入更多字符,请继续
idx=*s-'a';
如果(根->α[idx]){
root->alpha[idx]=trie_delete(root->alpha[idx],s+1);
如果(!root->alpha[idx]){
//已删除子节点,设置为1
收获=1;
}
}
}
//如果出现以下两种情况,我们可以删除此项:
//1.reap设置为1,只有在以下情况下才可能:
//我们现在在字符串的末尾,使用root->val
//设置为1,但现在设置为0
//b.子节点已被删除
//2.以当前节点结尾的字符串不在trie中,
//所以root->val=0
如果(收割&&!根->值){
对于(i=0;iα[i]){
收获=0;
打破
}
}
//没有更多子节点,请删除此节点
如果(收获){
三重自由(根);
root=NULL;
}
}
返回根;
}
每个节点都有一条边进入,所以你可以在边上或它们指向的节点上画字母;这是同一件事。好吧,但我说边有权重,而不是节点,或者我有吗?你可以用任何对你更有意义的方式来思考。没关系。@user2560730 Yes、 (据我所见)认为边有字母比节点有字母要自然得多。这是有限状态机的表示方式,尝试实际上只是它们的特例。这个条件(在插入函数中)有什么用途:if(!input)返回根;它检查input
参数是否为空指针。如果为空指针,则没有字符串,因此我们只返回根。嗨,用户2560730,我可以知道我的代码是否帮助您理解trie删除吗?抱歉@yanhan,我发现您的代码有点难以理解,因此我尝试计算trie d我自己的元素,幸运的是我做对了。但是谢谢你的努力。