zoukankan      html  css  js  c++  java
  • GeekforGeeks Trie

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/,未经本作者同意不得转载。

    https://blog.csdn.net/kenden23/article/details/24453639

    Trie是非常高效的信息检索数据结构, 时间效率会是O(m),当中m是须要搜索的keyword的长度。

    缺点就是须要的存储空间大。

    Trie的特点:

    1. 每一个Trie的节点都由多个分支构成

    2. 每一个分支代表可能的keyword的一个字符

    3. 须要mark(标志)每一个keyword的最后一个字符为leaf node(叶子节点)

    英文字母的节点数据结构能够表演示样例如以下:

    struct TrieNode
    {
    	int value; /* Used to mark leaf nodes */
    	TrieNode *children[ALPHABET_SIZE];
    };


    插入keyword:

    1. keyword的每一个字符都作为独立的trie节点, 注意每一个子节点都是一组指针,指向下一个trie节点。

    2 假设输入的keyword是新的,或者是比原有keyword长, 就须要构造新的节点, 并且须要标志它的结束点为叶子节点。 

    3. 假设keyword比原有的某个keyword短,那么就能够仅仅标志新的叶子节点。

    4. keyword的长度决定了trie的深度


    搜索keyword:

    1. 比較keyword的字符。然后往下一层移动

    2. 假设keyword结束,或者没有这个字符在trie中,那么搜索结束。 前者比較最后一个节点是否是叶子节点,假设是表示搜索成功,否则不成功。后者表示搜索不成功。

    參考原文:

    http://www.geeksforgeeks.org/trie-insert-and-search/

    实现程序:

    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <string>
    
    #define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
    #define ALPHABET_SIZE (26)
    #define CHAR_TO_INDEX(c) ((int)c - (int)'a')
    
    struct TrieNode
    {
    	int value; /* Used to mark leaf nodes */
    	TrieNode *children[ALPHABET_SIZE];
    };
    
    struct TrieT
    {
    	TrieNode *root;
    	int count;
    };
    
    // Returns new trie node (initialized to NULLs)
    TrieNode *getNode(void)
    {
    	TrieNode *pNode = NULL;
    	pNode = (TrieNode *)malloc(sizeof(TrieNode));
    
    	if( pNode )
    	{
    		int i;
    		pNode->value = 0;
    		for(i = 0; i < ALPHABET_SIZE; i++)
    		{
    			pNode->children[i] = NULL;
    		}
    	}
    	return pNode;
    }
    
    // Initializes trie (root is dummy node)
    void initialize(TrieT *pTrie)
    {
    	pTrie->root = getNode();
    	pTrie->count = 0;
    }
    
    // If not present, inserts key into trie
    // If the key is prefix of trie node, just marks leaf node
    void insert(TrieT *pTrie, char key[])
    {
    	int level = 0;
    	int length = strlen(key);
    	int index = 0;
    	TrieNode *pCrawl;
    
    	pTrie->count++;
    	pCrawl = pTrie->root;
    
    	for( level = 0; level < length; level++ )
    	{
    		index = CHAR_TO_INDEX(key[level]);
    		if( !pCrawl->children[index] )
    		{
    			pCrawl->children[index] = getNode();
    		}
    		pCrawl = pCrawl->children[index];
    	}
    	// mark last node as leaf
    	pCrawl->value = pTrie->count;
    }
    
    // Returns non zero, if key presents in trie
    int search(TrieT *pTrie, char key[])
    {
    	int level;
    	int length = strlen(key);
    	int index;
    	TrieNode *pCrawl;
    
    	pCrawl = pTrie->root;
    	for( level = 0; level < length; level++ )
    	{
    		index = CHAR_TO_INDEX(key[level]);
    		if( !pCrawl->children[index] )
    		{
    			return 0;
    		}
    		pCrawl = pCrawl->children[index];
    	}
    	return (0 != pCrawl && pCrawl->value);
    }
    
    // Driver
    int main()
    {
    	// Input keys (use only 'a' through 'z' and lower case)
    	char keys[][8] = {"the", "a", "there", "answer", "any", "by", "bye", "their"};
    	TrieT trie;
    
    	char output[][32] = {"Not present in trie", "Present in trie"};
    
    	initialize(&trie);
    
    	// Construct trie
    	for(int i = 0; i < ARRAY_SIZE(keys); i++)
    	{
    		insert(&trie, keys[i]);
    	}
    
    	// Search for different keys
    	printf("%s --- %s
    ", "the", output[search(&trie, "the")] );
    	printf("%s --- %s
    ", "these", output[search(&trie, "these")] );
    	printf("%s --- %s
    ", "their", output[search(&trie, "their")] );
    	printf("%s --- %s
    ", "thaw", output[search(&trie, "thaw")] );
    
    	return 0;
    }


    更新 2014 5 -16

    C++写的类,主要是带构造函数和析构函数。能够非常好管理内存,甚至不须要递归地手动释放内存了,析构函数能够自己主动递归调用释放全部Node,这个是C++比C强大的地方之中的一个:

    class TrieInsertAndSearch
    {
    	const static int ALPH_SIZE = 26;
    
    	struct Node
    	{
    		int val;
    		Node *children[ALPH_SIZE];
    		explicit Node(int v = 0) : val(v)
    		{
    			for (int i = 0; i < ALPH_SIZE; i++)
    			{
    				children[i] = nullptr;
    			}
    		}
    		~Node()
    		{
    			for (int i = 0; i < ALPH_SIZE; i++)
    			{
    				if (children[i]) delete children[i];
    				children[i] = nullptr;
    			}
    		}
    	};
    	struct Tree
    	{
    		Node *root;
    		int count;
    		explicit Tree(int c = 0, Node *r = nullptr) : count(c), root(r){}
    		~Tree()
    		{
    			if (root) delete root;
    			root = nullptr;
    		}
    	};
    
    	Tree *pT;
    	void insert(char key[])
    	{
    		int len = strlen(key);
    		Node *pCrawl = pT->root;
    		pT->count++;
    		for (int lv = 0; lv < len; lv++)
    		{
    			int id = key[lv] - 'a';
    			if (!pCrawl->children[id])
    			{
    				pCrawl->children[id] = new Node;
    			}
    			pCrawl = pCrawl->children[id];
    		}
    		pCrawl->val = pT->count;
    	}
    	bool search(char key[])
    	{
    		int len = strlen(key);
    		Node *pCrawl = pT->root;
    		for (int lv = 0; lv < len; lv++)
    		{
    			int id = key[lv] - 'a';
    			if (!pCrawl->children[id]) return false;
    			pCrawl = pCrawl->children[id];
    		}
    		return (pCrawl && pCrawl->val);
    	}
    public:
    	TrieInsertAndSearch()
    	{
    		char keys[][8] = {"the", "a", "there", "answer", "any", "by", "bye", "their"};
    		pT = new Tree(0, new Node);
    		int n = sizeof(keys) / sizeof(keys[0]);
    		for (int i = 0; i < n; i++)
    		{
    			insert(keys[i]);
    		}
    
    		// Search for different keys
    		if (search("the")) printf("the is in Trie
    ");
    		else printf("the is not in Trie
    ");
    		if (search("these")) printf("these is in Trie
    ");
    		else printf("these is not in Trie
    ");
    		if (search("their")) printf("their is in Trie
    ");
    		else printf("their is not in Trie
    ");
    		if (search("thaw")) printf("thaw is in Trie
    ");
    		else printf("thaw is not in Trie
    ");
    	}
    	~TrieInsertAndSearch()
    	{
    		if (pT) delete pT;
    		pT = nullptr;
    	}
    };



查看全文
  • 相关阅读:
    Android笔记之AsyncTask
    Android笔记之使用Glide加载网络图片、下载图片
    Android笔记之OnLongClickListener
    Android笔记之ViewModel的使用示例
    分享两款好玩的单机游戏^_^
    Android笔记之Retrofit与RxJava的组合
    15张扑克,让观众心选一张,然后分成3组,每组5张。通过询问观众心选的牌是否在于某组中,最后把选中的牌找出来。
    使用Retrofit发送POST请求提交JSON数据
    Android笔记之引用aar
    不可变类
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10566600.html
  • Copyright © 2011-2022 走看看