trie树实现模糊查找

        在上一篇博客里简单的说了一下标准trie树的建立,本来说要做一个小型词典来用试试,结果这段时间有事就一直耽误到现在,今天抽了一点时间看看,首先我想到的是在我们输入某些单词的前面几个字母的时候下面的提示,那是trie树的模糊查找,便想了想去实现这个功能。

       要想实现模糊查询,首先一点是得找到前缀所在的节点,例如我想查找以ac开头的单词,那么在建立了trie树之后就得在trie树中首先找到ab所在的节点,然后在考虑里面的是。这一步其实好实现,就跟插入单词基本相似一个个的匹配就完了。找到前缀所在的节点之后就得考虑在这个节点之内怎么找到我们想要的单词,基本的思路是,判断该节点处的单词标记是否是true如果是就表示这个单词应该匹配出来,那么问题来了,我直到它是要匹配出来的可我要怎么把它实现出来?还有匹配到了之后我还不能结束还要一直匹配下去,又应该怎么搞?

     对于第一个问题,很容易想到用一个变量先逐个保存起来,匹配成功之后在将它保存到一个数组中去,而这个数组就专门用来保存所有匹配到的单词。

     至于第二个问题,我想了较长一段时间,因为老是匹配的不对,尤其是前一个单词是后一个单词的一个前缀的时候,例如匹配到abc之后还要匹配abcd,abc匹配之后保存单词的数组就要向前推进前面保存的数据就会丢失,当时我想的是数组的下一个值的初始值就上一个单词,后来一想实在是太蠢了,如果还要匹配abdf不是GG了?正在愣住之际忽然想起迭代,哎呀,终于找到症结了,我把单词前缀作为一个变量传进去,再迭代赋值不就OK?

      好了,有了解决方案就开始写了(很多程序员一开始都有这个毛病,觉得听懂了,想明白了,好简单,不去动手写,结果真到写的时候才发现什么都不会),经过一番折腾相对完善的代码如下

//模糊搜索单词
	public String [] getwordsBypre(String wordPre){
		String[] result=null;
		wordPre=wordPre.trim().toLowerCase();
		char []letters=wordPre.trim().toCharArray();
		TrieNode node=root;
		for(int i=0;i<letters.length;i++){
			int pos=letters[i]-'a';
			if(node.sons[pos]==null){
				break;
			}else{
				node=node.sons[pos];
			}
		}
		if(node.isEnd){//本身是一个单词也要匹配到
			words[wordsNum++]="";//words是一个全局变量,在构造函数中初始化全部赋值为""
		}
		for(TrieNode child:node.sons){
			getAllNext("",child);
		}
		result=new String[wordsNum];
		for(int i=0;i<wordsNum;i++){
			result[i]=wordPre+words[i];
		}
		return result;
	}
	//获得一个节点下的所有的单词
	private void getAllNext(String pre,TrieNode node){	
		if(wordsNum>=10){//这里我是根据实际情况做了一个限制不要模糊匹配那么多,10个够了
			return ;
		}
		if(node!=null){
			pre+=node.value;//pre是单词前缀,在后面的迭代过程中随着节点的不断深入,pre也要保存前面节点的值
			if(node.isEnd){	
				words[wordsNum]=pre+words[wordsNum];
				wordsNum++;
			}
			for(TrieNode child:node.sons){
				getAllNext(pre,child);//迭代
			}
		}
	}

这里是直接写到trie树这个结构里面的方法,就是我写的那个标准的trie树(http://blog.csdn.net/my_sunshine_y/article/details/50497936)。测试类代码:

package TrieTree;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

public class test {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		InputStream iis=test.class.getClassLoader().getResourceAsStream("a.txt");
		myTrie t=new myTrie();
		InputStreamReader isr=new InputStreamReader(iis);
		BufferedReader br=new BufferedReader(isr);
		String str ="";
		while((str = br.readLine())!=null&&!str.trim().equals("")){
			String word=str.trim();
			System.out.println(word);
			t.insertWord(word);
		}
		System.out.println(t.findWord("abc"));
		System.out.println();
		String [] re=t.getwordsBypre("ai");
		for(String s:re){
			System.out.println(s);
		}
	}

}

其中a.txt在我工程目录下,这里通过类加载器来读取。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的 C 语言字典 Trie 的代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_WORD_LEN 100 typedef struct TrieNode { char value; struct TrieNode *children[26]; int is_end; } TrieNode; TrieNode *createNode(char value) { TrieNode *node = (TrieNode *) malloc(sizeof(TrieNode)); node->value = value; for (int i = 0; i < 26; i++) { node->children[i] = NULL; } node->is_end = 0; return node; } void insert(TrieNode *root, char *word) { TrieNode *curr = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { curr->children[index] = createNode(word[i]); } curr = curr->children[index]; } curr->is_end = 1; } int search(TrieNode *root, char *word) { TrieNode *curr = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { return 0; } curr = curr->children[index]; } return curr->is_end; } int main() { TrieNode *root = createNode('\0'); char word[MAX_WORD_LEN]; int choice = 0; do { printf("1. Insert Word\n"); printf("2. Search Word\n"); printf("3. Exit\n"); printf("Enter Choice: "); scanf("%d", &choice); switch (choice) { case 1: printf("Enter Word to Insert: "); scanf("%s", word); insert(root, word); break; case 2: printf("Enter Word to Search: "); scanf("%s", word); if (search(root, word)) { printf("%s is present in the dictionary.\n", word); } else { printf("%s is not present in the dictionary.\n", word); } break; case 3: printf("Exiting...\n"); break; default: printf("Invalid Choice!\n"); break; } } while (choice != 3); return 0; } ``` 该实现中使用了一个 TrieNode 结构体来表示 Trie 中的每个节点,其中包含了节点的值,子节点指针数组和一个标志位,用于指示该节点是否为单词的结尾。 在插入单词时,从根节点开始遍历 Trie ,如果当前节点的相应子节点为空,则新建一个节点并将其作为当前节点的相应子节点。最后将单词的结尾节点的标志位设置为 1。 在查找单词时,同样从根节点开始遍历 Trie ,如果当前节点的相应子节点为空,则说明该单词不存在于 Trie 中。如果单词的最后一个字符所在的节点的标志位为 1,则说明该单词存在于 Trie 中。 该实现中还包含了一个简单的命令行界面,用于接收用户的输入并执行相应的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值