三元搜索trie插入函数问题

时间:2014-02-26 17:04:59

标签: c trie ternary-search-tree

所以我正在尝试进行三元搜索。现在,我只是在处理插入功能。我已经理解了网上三元搜索的基本思想。我知道一个根节点有3个叶子,如果角色在根之前,它会在左边,在右边之后,如果它与根匹配,它会到达中间叶子。因此,我的主要目标是制作一个程序,可以为错误拼写的用户输入的单词建议单词。但目前我正在努力制作三元搜索特里。我使用trie制作一本字典,用它来检查用户输入的单词以建议下一个最佳选择。但是现在,只需要将一些字符输入到三元组中,当我显示它时,应该按顺序显示它。 我不是100%肯定我对中叶的逻辑。现在我的程序在运行时,给了我一些垃圾无限值,以某种方式与输入的最后一个字符相关。我不知道我哪里出错了。有人可以指出我犯了哪些错误吗?另外,如果我写的任何逻辑都错了,你能告诉我吗?我的意思是,你不必给我代码或任何东西,因为一旦我明白我出错了,我觉得自己有能力做到这一点,但如果有人能帮助我找到错误,那将有助于我很多!

整个代码:

#include <stdio.h>
#include <stdlib.h>  //Because usage of malloc gives warnings without this header
typedef struct tstree
{
    struct tstree *lokid;
    struct tstree *hikid;
    struct tstree *eqkid;
    char letter;
}node;
node *head = NULL;
int count = 0;
int insert(char x, node **head)
{
    if (*head==NULL)            //If it's the first element
    {
        *head = malloc(sizeof(node));   
        (*head)->letter = x;
        count++;            
        (*head)->lokid = (*head)->hikid = (*head)->eqkid = NULL;            //Assign all 3 to null initially
    }
    else if ((*head)->letter == x)          //If equal, insert below
    insert(x , &((*head)->eqkid) );
    else if ((*head)->letter > x)   //If inserted char comes before current val, insert to left
    insert(x,&(*head)->lokid);
    else
    insert(x,&(*head)->hikid);              //Else to the right
    return 0;
}
void display(node *head)
{
    if(head)
    {
        display(head->lokid);               //print in infix order
        printf("%c ",head->letter);
        display(head->hikid);
    }
    //return 0;
}
int main()
{   
    int op;
    char num;
    printf("\nWelcome Fabiz. Hope it meets your expectations!\n");
    while(1)
    {
        printf("\n1. To insert an element\n2. Display the tree\n3. Exit\nOption :");
        scanf("%d",&op);
        switch(op)
        {
            case 1:
            {
                system("clear");
                printf("\nEnter the element : ");
                scanf(" %c",&num);
                insert(num,&head);
                break;
            }
            case 2:
            {
                system("clear");
                if(count == 0)
                printf("\nEmpty tree\n");
                else
                {
                    printf("Display in order..\n");
                    display(head);
                }
                break;
            }
            default: exit(0);
        }
    }
    return 0;
}

我正在使用Geany文本编辑器,我在Linux Mint上。我遇到了一个问题,在编译器中只打印出我点击显示功能时无限输入的最后一个字符。 任何帮助都会非常有帮助! 谢谢!

1 个答案:

答案 0 :(得分:3)

您的显示功能有误。循环条件永远不会计算为false:

while(&(*head)->lokid!=NULL && &(*head)->hikid!=NULL)

这不是你想要的。 &(*head)->lokid&(*head)->hikid无法评估为NULL。如果head不是NULL,则&(*head)->lokid*head的地址相同,加上lokidstruct tstree的偏移量。请注意,您的循环甚至没有可能使条件为假的更新语句,并且它没有任何break - 它注定要失败。

事实上,你甚至根本不需要循环。要按顺序打印,这就是您所需要的:

void display(node *head) {
    if (head) {
        display(head->lokid);
        printf("%c ", head->letter);
        display(head->hikid);
    }
}

请注意,传递node **没有任何意义(我将其更改为node *),返回值应为void

<强>更新

您的insert()函数是正确的,但您在main中使用了错误的变量。来自insert()的递归基础中的此赋值导致意外行为:

temp = *head = malloc(sizeof(node));

请注意,每次点击基本案例时,都会将新节点分配给*headtemp,从而失去对temp之前存储的内容的引用。然后你拨打display(temp)。是的,您构建了trie,但是从最后插入的节点开始打印它 - 而不是您想要的。

相反,您应该使用全局变量display调用head,这是您的trie的正确根目录:

display(head);

调用insert时会发生同样的情况。您不希望在最后添加的节点上插入新的字母,您希望在根上添加它。 main()应该改为:

insert(num, &head);

虽然我们已经注意到了,但请注意temp完全没必要。你不需要它。 insert通过引用操纵全局头,temp在这里没用(事实上它引入了一个bug)。

在main中更改这两行就足够了,在这里进行测试,它就像魅力一样。