2016-07-27 43 views
-1

我一直在努力实现一个C++实现特里数据结构的插入,通过博客的工作,其中有几件事情我无法理解http://theoryofprogramming.com/2015/01/16/trie-tree-implementation/
什么下面的语句在执行的尝试做

#define ALPHABETS 26 
#define CASE 'a' 
#define MAX_WORD_SIZE 25 
using namespace std; 

struct Node 
    { 
    struct Node * parent; 
    struct Node * children[ALPHABETS]; 
    vector<int> occurrences; 
    }; 

    // Inserts a word 'text' into the Trie Tree 
    // 'trieTree' and marks it's occurence as 'index'. 

    void InsertWord(struct Node * trieTree, char word[], int index) 
    { 
    struct Node * traverse = trieTree; 
    while (*word != '\0') { // Until there is something to process 
    if (traverse->children[*word - CASE] == NULL) { 

     // There is no node in 'trieTree' corresponding to this alphabet 

     // Allocate using calloc(), so that components are initialised 
     traverse->children[*word - CASE] = (struct Node *) calloc(1, sizeof(struct Node)); 
     traverse->children[*word - CASE]->parent = traverse; // Assigning parent 
    } 

    traverse = traverse->children[*word - CASE]; 
    ++word; // The next alphabet 
} 

    traverse->occurrences.push_back(index);  // Mark the occurence of the word 
} 

// Prints the 'trieTree' in a Pre-Order or a DFS manner 
// which automatically results in a Lexicographical Order 
void LexicographicalPrint(struct Node * trieTree, vector<char> word) 
    { 
    int i; 
    bool noChild = true; 
    if (trieTree->occurrences.size() != 0) { 
    // Condition trie_tree->occurrences.size() != 0, 
    // is a neccessary and sufficient condition to 
    // tell if a node is associated with a word or not 
    vector<char>::iterator charItr = word.begin(); 
    while (charItr != word.end()) { 
     printf("%c", *charItr); 
     ++charItr; 
    } 
    printf(" -> @ index -> "); 

    vector<int>::iterator counter = trieTree->occurrences.begin(); 
    // This is to print the occurences of the word 

    while (counter != trieTree->occurrences.end()) { 
     printf("%d, ", *counter); 
     ++counter; 
    } 

    printf("\n"); 
} 

for (i = 0; i < ALPHABETS; ++i) { 
    if (trieTree->children[i] != NULL) { 
     noChild = false; 
     word.push_back(CASE + i); // Select a child 

     // and explore everything associated with the cild 
     LexicographicalPrint(trieTree->children[i], word); 
     word.pop_back(); 
     // Remove the alphabet as we dealt 
     // everything associated with it 
    } 
} 

    word.pop_back(); 
} 

int main() 
    { 
    int n, i; 
    vector<char> printUtil;  // Utility variable to print tree 
    // Creating the Trie Tree using calloc 
    // so that the components are initialised 
    struct Node * trieTree = (struct Node *) calloc(1, sizeof(struct Node)); 
    char word[MAX_WORD_SIZE]; 
    printf("Enter the number of words-\n"); 
    scanf("%d", &n); 
    for (i = 1; i <= n; ++i) { 
    scanf("%s", word); 
    InsertWord(trieTree, word, i); 
    } 

    printf("\n"); // Just to make the output more readable 
    LexicographicalPrint(trieTree, printUtil); 

return 0; 
} 

我无法理解在insertword本声明:

 if (traverse->children[*word - CASE] == NULL) 


也正如我们在主函数初始化所有元素为1,则我们怎么能成为空?

回答

0

功能InsertWord()动态地向树中添加一个新字,并且在该过程中,每当该字的前缀与树中已经添加的另一个字的前缀不匹配时,创建新节点。

这正是您的生产线正在测试的内容。从我所看到的,traverse是一个指向当前节点的单词前缀。 *word是前缀后的单词中的下一个字符。如果与当前k -prefix对应的节点没有子标签(指针为NULL)且标签对应下一个字符,则表示我们必须为下一个k+1分配一个新节点 - 该词的前缀。

+0

但是为什么我们要减去在这种情况下是'a'的字符大小写 – Mark

+0

对于这个实现,'ALPHABETS'常量设置为26,这是每个节点的子节点数。当我们从字符串的每个字符中减去“a”时,我们可以有效地找到每个字符要去哪个孩子。例如,'a'变成'0','b'变成'1',..,''z''变成25. –

+0

你能告诉我们,因为我们初始化结构为1 ()那么我们如何将traverse-> children [* word-case]与NULL进行比较,是不是应该将它与1进行比较。如果我在某处出错,请更正我。 – Mark

相关问题