搜索引擎作业:基于字典树(前缀树)的智能提示Java实现

记录一下写过的代码,也欢迎各位大佬指正!

使用长度为26的数组实现字典树(存储英文):

package cn.fosu.java;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;

class TrieNode {
    public char data;
    public TrieNode[] children;
    public boolean isEndingChar;

    public TrieNode(char data) {
        this.data = data;
        isEndingChar = false;
        children = new TrieNode[26];
    }
}

public class Trie {
    private final TrieNode root = new TrieNode('/');
    private TrieNode curr;

    public void insert(char[] pattern) {
        curr = root;
        try {
            for (char p : pattern) {
                int index = p - 'a';
                if (curr.children[index] == null) {
                    TrieNode newNode = new TrieNode(p);
                    curr.children[index] = newNode;
                }
                curr = curr.children[index];
            }
            curr.isEndingChar = true;
        } catch (ArrayIndexOutOfBoundsException ignored) {
        }
    }

    public boolean find(char[] pattern) {
        curr = root;
        for (char p : pattern) {
            int index = p - 'a';
            if (curr.children[index] == null) {
                return false;
            }
            curr = curr.children[index];
        }
        return curr.isEndingChar;
    }

    public boolean isExist(String str) {
        return curr.data == (int) str.charAt(str.length() - 1);
    }

    public String tips(String str) {
        StringBuilder sb = new StringBuilder("提示:");
        TrieNode temp;
        for (int i = 0; i < 26; ++i) {
            temp = curr;
            if (temp.children[i] != null) {
                sb.append(" ");
                sb.append(str);
                sb.append(temp.children[i].data);
                temp = temp.children[i];
                while (!temp.isEndingChar) {
                    for (int j = 0; j < 26; ++j) {
                        if (temp.children[j] != null) {
                            sb.append(temp.children[j].data);
                            temp = temp.children[j];
                            break;
                        }
                    }
                }
            }
        }
        return sb.toString();
    }

    public char[] transfer(String s) {
        char[] temp = new char[s.length()];
        for (int i = 0; i < s.length(); ++i) {
            temp[i] = s.charAt(i);
        }
        return temp;
    }

    public void readFile(String filepath) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(filepath));
            String str;
            while ((str = br.readLine()) != null) {
                insert(transfer(str.replaceAll(" ", "")));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Trie t = new Trie();
        t.readFile("data/word.txt");
        System.out.println("请输入关键词:(输入“:q“退出程序)");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            while (true) {
                String str = br.readLine().replaceAll(" ", "");
                if (str.equals(":q")) break;
                if (!t.find(t.transfer(str))) {
                    if (t.isExist(str)) {
                        System.out.println("你可能要找的是:");
                        System.out.println(t.tips(str));
                    } else {
                        System.out.println("没有搜索到相关内容");
                    }
                } else {
                    System.out.println("你可能要找的是:");
                    System.out.println(t.tips(str));
                }
            }
        } catch (ArrayIndexOutOfBoundsException | IOException ignored) {
        } catch (StringIndexOutOfBoundsException e) {
            System.out.println("输入了无关字符");
        } finally {
            System.out.println("程序已退出...");
        }
    }
}

使用HashMap实现:

package cn.fosu.java;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

class TrieNodeCN {
    public Map<Character, TrieNodeCN> childMap;
    public boolean isEnding = false;

    public TrieNodeCN() {
        childMap = new HashMap<>();
    }
}

public class TrieHash {
    private final TrieNodeCN root = new TrieNodeCN();
    private TrieNodeCN curr;
    private StringBuilder prev;

    public void insert(String word) {
        curr = root;
        for (int i = 0; i < word.length(); ++i) {
            char c = word.charAt(i);
            if (!curr.childMap.containsKey(c)) {
                curr.childMap.put(c, new TrieNodeCN());
            }
            curr = curr.childMap.get(c);
        }
        curr.isEnding = true;
    }

    public boolean find(String word) {
        prev = new StringBuilder();
        curr = root;
        for (int i = 0; i < word.length(); ++i) {
            char c = word.charAt(i);
            if (!curr.childMap.containsKey(c)) {
                return false;
            }
            prev.append(word.charAt(i));
            curr = curr.childMap.get(c);
        }
        return curr.isEnding;
    }

    public boolean isExist() {
        return !curr.childMap.isEmpty();
    }

    public String tips() {
        String pre = prev.toString();
        StringBuilder sb = new StringBuilder();
        TrieNodeCN temp;
        int i = 1;
        for (Character key : curr.childMap.keySet()) {
            temp = curr.childMap.get(key);
            sb.append(i++);
            sb.append("、");
            sb.append(pre);
            sb.append(key);
            while (!temp.childMap.isEmpty()) {
                if (temp.isEnding) break;
                char fk = (char) temp.childMap.keySet().toArray()[0];
                sb.append(fk);
                temp = temp.childMap.get(fk);
            }
            sb.append(" ");
        }
        return sb.toString();
    }

    public void readFile(String filepath) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(filepath));
            String str;
            while ((str = br.readLine()) != null) {
                insert(str.trim());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        TrieHash th = new TrieHash();
        th.readFile("data/wordCN.txt");
        System.out.println("请输入:(输入“:q“退出程序)");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            while (true) {
                String str = br.readLine().trim();
                if (str.equals(":q")) break;
                if (th.find(str)) {
                    if (th.isExist()) {
                        System.out.println("你可能要找的是:");
                        System.out.println(th.tips());
                    }
                } else {
                    if (th.isExist()) {
                        System.out.println("你可能要找的是:");
                        System.out.println(th.tips());
                    } else {
                        System.out.println("没有搜索到相关内容");
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException | IOException ignored) {
        } catch (StringIndexOutOfBoundsException e) {
            System.out.println("输入了无关字符");
        } finally {
            System.out.println("程序已退出...");
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值