c++ 字典树

实现插入和查询

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>

using namespace std;

struct Node
{
    bool isWord;//判断当前字母是否为单词的最后一个字母标识
    Node *next[26];//26叉
    Node()
    {
        isWord = false;
        for (int i = 0; i != 26; ++i)
        {
            next[i] = NULL;//清空26叉
        }
    }
};
class DicTree
{
public:
    Node *root;//根节点
    DicTree()
    {
        root = NULL;//在构造函数中初始化
    }
    void Insert(string str)
    {
        if (!root)
        {
            root = new Node;//如果root现在不空,需要重新开辟一个根节点
        }
        Node *head = root;//根节点不能变,找一个新的指针指向根节点方便操作
        for (long int i = 0; i != str.length(); ++i)
        {
            int num = str[i] - 'a';//获取当前字母应该存储的位置
            if (head->next[num] == NULL)
            {
                head->next[num] = new Node;
            }
            head = head->next[num];
        }
        head->isWord = true;
    }
    bool Search(string str)
    {
        Node *head = root;
        for (long int i = 0; i != str.length(); ++i)
        {
            int num = str[i] - 'a';
            if (head->next[num] == NULL)
            {
                return false;
            }
            else
            {
                head = head->next[num];
            }
        }
        return head->isWord;
    }
};

int main(int argc, const char * argv[])
{
    string inp1;
    DicTree A;
    while (cin >> inp1, inp1 != "quit")
    {
        A.Insert(inp1);
    }

    cout << "-----------------------------" << endl;
    cout << "input end" << endl;
    cout << "-----------------------------" << endl;

    string inp2;
    while (cin >> inp2, inp2 != "quit")
    {
        bool res = A.Search(inp2);
        cout << res << endl;
    }

    system("pause");
    return 0;
}

 

 

完整版实现

#include <queue>
#include <iostream>
using namespace std;

const int maxs = 26;

struct TrieTreeNode
{
    char val;
    bool isEnd;
    int childCnt;
    int prefixCnt;
    TrieTreeNode *child[maxs];
    TrieTreeNode(char _val)
        :val(_val), isEnd(false), childCnt(0), prefixCnt(0)
    {
        memset(child, NULL, sizeof(child));//not 26!!
    }
};

void Insert(TrieTreeNode * root, const char *word)
{
    TrieTreeNode * p = root;
    for (int i = 0; i < strlen(word); i++)
    {
        if (p->child[word[i] - 'a'] == NULL)
        {
            p->child[word[i] - 'a'] = new TrieTreeNode(word[i]);
            p->childCnt++;
        }

        p->child[word[i] - 'a']->prefixCnt++;
        p = p->child[word[i] - 'a'];
    }
    p->isEnd = true;
}

bool find(TrieTreeNode * root, const char * word)
{
    TrieTreeNode * p = root;
    int len = strlen(word);
    for (int i = 0; i < len; i++)
    {
        int c = word[i] - 'a';
        if (p->child[c] == NULL)
        {
            return false;
        }
        p = p->child[c];
    }
    return p->isEnd;
}


void levelOrderTraverse(TrieTreeNode * root)
{
    if (root == NULL)
        return;

    queue<TrieTreeNode *> q;
    q.push(root);

    while (!q.empty())
    {
        TrieTreeNode *p = q.front();
        cout << p->val << "(" << p->childCnt << ")";
        for (int i = 0; i < maxs; i++)
        {
            if (p->child[i] != NULL)
            {
                q.push(p->child[i]);
            }
        }
        q.pop();
    }
    cout << endl;
}


void preOrderTraverse(TrieTreeNode * treeNode)
{
    if (treeNode != NULL)
    {
        cout << treeNode->val << "(" << treeNode->childCnt << ")";
        for (int i = 0; i < maxs; i++)
        {
            preOrderTraverse(treeNode->child[i]);
        }
    }
}

void PostOrderTraverse(TrieTreeNode * treeNode)
{
    if (treeNode != NULL)
    {
        for (int i = 0; i < maxs; i++)
        {
            PostOrderTraverse(treeNode->child[i]);
        }
        cout << treeNode->val << "(" << treeNode->childCnt << ")";
    }
}

void makeEmpty(TrieTreeNode * root)
{
    if (root != NULL)
    {
        for (int i = 0; i < 26; i++)
        {
            makeEmpty(root->child[i]);
        }
        delete root;
    }
    root = NULL;
}

void buildTrieTree(TrieTreeNode * root, const char* words[], int n)
{
    for (int i = 0; i < n; i++)
    {
        Insert(root, words[i]);
    }
}

bool Remove(TrieTreeNode * root, const char *word, int pos, int n)
{
    if (pos == n)
    {
        root->isEnd = false;
        return root->childCnt;
    }
    if (root->child[word[pos] - 'a'] == NULL)
        return false;

    if (Remove(root->child[word[pos] - 'a'], word, pos + 1, n))
    {
        delete root->child[word[pos] - 'a'];
        root->child[word[pos] - 'a'] = NULL;

        root->prefixCnt--;
        if (--root->childCnt == 0 && root->isEnd == false)
        {
            return true;
        }

    }
    return false;
}

int countWordsWithPrefix(TrieTreeNode * root, const char *prefix)
{
    TrieTreeNode *p = root;

    for (int i = 0; i < strlen(prefix); i++)
    {
        if (p->child[prefix[i] - 'a'] == NULL)
        {
            return 0;
        }
        p = p->child[prefix[i] - 'a'];
    }
    return p->prefixCnt;
}


int main()
{
    TrieTreeNode *root = new TrieTreeNode('\0');
    const char *words[] = { "abc", "ad", "ef" };
    buildTrieTree(root, words, sizeof(words) / sizeof(words[0]));
    levelOrderTraverse(root);
    cout << '\n';
    preOrderTraverse(root);
    cout << '\n';
    PostOrderTraverse(root);
    cout << "\n";

    if (find(root, "ef"))
        cout << "ef found" << endl;
    else 
        cout << "ef not found" << endl;

    Insert(root, "e");

    levelOrderTraverse(root);

    Remove(root, "ef", 0, strlen("ef"));

    levelOrderTraverse(root);

    Remove(root, "e", 0, strlen("e"));
    levelOrderTraverse(root);

    cout << countWordsWithPrefix(root, "a") << endl;
    Remove(root, "ad", 0, strlen("ad"));
    cout << countWordsWithPrefix(root, "a") << endl;

    makeEmpty(root);



    system("pause");
    return 0;
}

 

posted @ 2020-09-19 10:42  r1-12king  阅读(235)  评论(0编辑  收藏  举报