Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Trie的麻烦_C_Trie - Fatal编程技术网

C Trie的麻烦

C Trie的麻烦,c,trie,C,Trie,所以,我试图阅读一个Trie,对我来说是一个相对较新的数据结构。在我读过的地方,trie中的每个节点都由一个整数变量组成,该变量将标记一个单词的结尾,还将由26个指针组成,每个指针指向较低级别的节点(假设单词只包含小写字母字符) 现在我面临的问题是,无论我在哪里看到/阅读实现,它们都会用一个字符标记节点。就像在这种情况下: 但就我理解崔的方式而言,我相信每一条边都应该被标记为一个字符。尽管如此,我知道我们没有用于边缘的数据结构,只是用于节点。但是标记边缘不是更正确吗 另外,这是我实现inser

所以,我试图阅读一个Trie,对我来说是一个相对较新的数据结构。在我读过的地方,trie中的每个节点都由一个整数变量组成,该变量将标记一个单词的结尾,还将由26个指针组成,每个指针指向较低级别的节点(假设单词只包含小写字母字符)

现在我面临的问题是,无论我在哪里看到/阅读实现,它们都会用一个字符标记节点。就像在这种情况下:

但就我理解崔的方式而言,我相信每一条边都应该被标记为一个字符。尽管如此,我知道我们没有用于边缘的数据结构,只是用于节点。但是标记边缘不是更正确吗

另外,这是我实现insert的算法。如果你发现有什么问题,请告诉我

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我自己的元素,幸运的是我做对了。但是谢谢你的努力。