【问题标题】:Help with Trie implementation帮助实现 Trie
【发布时间】:2011-08-27 21:32:55
【问题描述】:

我一直在尝试在 C 中实现将字符插入到 trie 数据结构中的基本功能。我一直在试图找出我做错了什么,但在最后一天左右我被难住了/卡住了.

这是我写的一些代码:

TR head = NULL;

void initDict () {
  head = NULL;
}

TR newNode (char item) {
  TR temp;
  temp = malloc (sizeof(*temp));
  temp->thisChar = item;
  temp->child = NULL;
  temp->sibling = NULL;
  return temp;
}


TR insertInOrder (char item, TR trie) {
  if (trie == NULL) {
    trie = newNode(item);
  } else if (trie->thisChar < item) {
        insertInOrder(item, trie->sibling);
    } else if (trie->thisChar > item) {
        char temp = trie->thisChar;
        trie->thisChar = item;
        insertInOrder(temp, trie->sibling);
    }
    return trie;
}

void insert (char *word) {
  char letter = *word;
    TR temp = NULL;

    while (*word != '\0') {
        letter = *word;
        if (head == NULL) {
            head = newNode(letter);
            temp = head->child;
            word++;
        } else {
            temp = insertInOrder(letter, temp);
            temp->child = head->child;
            head->child = temp;
            word++;
        }
    }
}

我想不通...

P.S checkLetter,是一个布尔函数,检查字母是否已经在trie内(通过遍历trie结构,即trie = trie->sibling)

任何帮助将不胜感激 =]

干杯!

编辑:更改了我的代码,以便 insertInOrder 返回一个值,但由于 insert 是一个 void 函数并且必须保持为 void 函数,我不知道有一种方法可以将节点进一步插入到 trie 的头部(即 head->child、head->child->child 等)

【问题讨论】:

  • 是的,它可以编译,除了客户端、头文件和它编译的缺少的 checkLetter 函数之外,但是在 insert() 函数中 temp = temp->child 行周围出现了段错误
  • 删除了我的评论。刚刚注意到你的 TR typedef。虽然不喜欢。非常混乱

标签: c trie


【解决方案1】:

在您的 insertInOrder 函数开始时,您检查是否需要分配一个新节点。然后根据需要分配一个新节点,但将新节点的地址存储在本地,一旦返回就会消失。

感觉也许 insertInOrder 函数应该返回一个 TR 来让 insert 做些好事?

【讨论】:

  • 好的,这是问题之一,非常感谢!现在似乎工作正常,但是在我返回节点后,我的 void 插入(必须保持 void)似乎无法将任何内容存储到 head->child 上,即我不知道我可以保留的方法向下移动 trie 并为其创建新节点
【解决方案2】:

你可以重新考虑你的插入算法:-)

我不是很好的老师,所以我只是给你解决方案,没有任何好的动机。虽然这没有编译和验证,但可以将其视为伪代码,让您了解我认为更好的算法,它可以处理您似乎错过的一些极端情况,并以不同的方式使用“头”指针来产生更一致的算法:

// 'head' is assumed to be a valid pointer, its 'child' field either NULL or a valid 
// pointer
TR currentNode = head;
while ( *word )
{
    assert(currentNode != NULL);

    if ( currentNode->child == NULL || currentNode->child->thisChar < *word )
    {
        // We need to insert a new node first in the child list
        TR newNode = malloc(sizeof *currentNode);
        newNode->thisChar = *word;
        newNode->sibling = currentNode->child;
        newNode->child = NULL;
        currentNode->child = newNode;
        currentNode = newNode;
    }
    else
    {
        // Find the place to insert next node
        currentNode = currentNode->child;
        while ( currentNode->sibling && currentNode->thisChar < *word )
            currentNode = currentNode->sibling;

        // If the current node already represents current character, we're done
        // Otherwise, insert a new node between the current node and its sibling
        if ( currentNode->thisChar != *word )
        {
            TR newNode = malloc(sizeof *currentNode);
            newNode->thisChar = *word;
            newNode->child = NULL;
            newNode->sibling = currentNode->sibling;
            currentNode->sibling = newNode;
            currentNode = newNode;
        }
    }
    word++;
}

【讨论】:

  • 你能给我解释一下,为什么newNode-&gt;sibling = currentNode-&gt;child那行让我很困惑
  • 新节点作为当前节点的子节点插入,因此任何现有的子节点都应该是新节点的兄弟节点。 (如果当前节点没有任何子节点,则该语句是多余但无害的)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 2011-05-21
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
  • 2010-10-15
相关资源
最近更新 更多