在c

时间:2015-10-10 21:24:06

标签: c sorting trie lexicographic preorder

所以我实现了一个将字存储在字典文件中的trie。我已经实现了插入操作;现在,我试图以字典方式打印。我很接近它,但我有一个小问题,我不知道如何解决。我也在努力记住程序的速度,这就是为什么我选择了一个数组或链表的trie。 以下是单个节点的样子:

struct node {
  int end;
  int occurrences;
  int superwords;
  struct node* child[26];
};

"端"表示单词的完成(例如,在单词簿中的字母' k'中结束== 1;这可以防止在检查单词是否实际插入树中时出现混淆)。

以下是方法:

void preorder(struct node *follow, char hold[200], int s){
  int i = 0;
  if(follow == NULL){
    return;
  }

  for(i = 0; i < 26; i++){
    if(follow->child[i] == NULL){
      continue;
    }
    else{
      printf("%c",'a'+i);
      hold[s] = 'a'+i;
      s++;
      if(follow->child[i]->end == 1){
        printf("\n");
        hold[s] = '\0';
        printf("%s", hold);
      }
      preorder(follow->child[i], hold, s);
    }
  }
  return;
}

我插入的词是:嘘,书,预订,约翰,特克斯,文字。它们应按顺序打印并分开。我的输出如下:

boo
book
booking
bookingjohn
bjohntex
bjtext
bjtext

我知道这可能与我的&#34; hold&#34;数组,存储单词的前缀,这样它们就不会丢失。我需要在某处将索引设置回零,以指示前缀及其所有相关单词的完成(boo,book,booking是一个很好的例子)但是还没有成功。任何帮助都会非常感激,我很乐意进一步澄清我的思考过程。

1 个答案:

答案 0 :(得分:2)

你非常接近。

在通过trie分支的for循环中存在两个问题:

else{
  printf("%c",'a'+i);
  hold[s] = 'a'+i;
  s++;

第一个问题是你打印(差不多)两次。在上面的代码段中,您将在跟踪树时打印前缀。然后当你到达单词的结尾时,你打印整个单词:

  if(follow->child[i]->end == 1){
    printf("\n");
    hold[s] = '\0';
    printf("%s", hold);
  }

因此根本不需要打印前缀,双重打印令人困惑。

其次,s参数表示树中的深度,即当前前缀的长度。因此在探索trie节点期间它应该是恒定的。但是每当你找到一个新分支时,你都会增加它(s++在上面的第一个片段中。您需要使用s + 1作为参数进行递归调用,而不是这样做,以便使用正确的前缀长度调用它。

您还可以简化控制结构。

以下是一个例子:

void preorder(struct node *follow, char hold[200], int s){
  int i = 0;
  if(follow == NULL){
    return;
  }
  /* Print the word at the beginning instead of the end */
  if (follow->end) {
    hold[s] = 0;
    printf("%s\n", hold);
  }

  for(i = 0; i < 26; i++){
    /* preorder returns immediately if its argument is NULL, so
     * there's no need to check twice. Perhaps even better would be
     * to do the check here, and not do it at the beginning.
     */
    hold[s] = 'a'+i;
    preorder(follow->child[i], hold, s + 1);
  }
}