2016-07-27 59 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