数学基础:四、树的应用1(利用树结构存储字典表)(待优化)

作业题:
https://time.geekbang.org/column/article/76481
利用树结构存储字典表,这里没有学习下一节(下一节的实现肯定更加高效)
这里只是用最简单的方法来实现(时间和空间复杂度都没有考虑)
代码如下:

public class Lesson11_1 {
    // 正则,只允许输入字母
    String regex = "^[A-Za-z]+$";

    // 构建字典对象
    class TreeNode {
        private char root;  // 根节点,最根节点构建时为0
        private boolean end; // 为end说明从根节点到此节点已结束,能遍历到说明能匹配
        private TreeNode[] leaves; // 子节点,存储非首字母

        public TreeNode(char c) {
            this.root = c;
            this.end = false;   // 默认没有结束,后面手动给结束
            this.leaves = new TreeNode[26]; // 给分配26个空间
        }

        // 私有方法(不用管),内部调用,往里面追加字母
        private TreeNode append(char c) {
            TreeNode[] leaves = this.leaves;
            TreeNode leaf = leaves[c - 'a'];    // 为相应下标0-25赋值
            if (leaf == null) { // 之前此节点下没有创建元素,需手动创建
                leaf = new TreeNode(c);
                leaves[c - 'a'] = leaf;
            }// 如果有该节点,直接返回即可,无需重复创建(否则可能覆盖掉之前该节点下的元素)
            return leaf;
        }

        // 存入单词
        public TreeNode build(String keyword) {
            if (keyword == null || keyword == "") {
                return this;
            }
            // 必须正确单词
            Assert.assertTrue(keyword.matches(regex));

            // 默认字典表数据都为小写字母
            keyword = keyword.toLowerCase();
            int length = keyword.length();
            TreeNode tmp = this;
            TreeNode root = this;   // 为了再最后返回,临时存储
            for (int i = 0; i < length; i++) {
                char c = keyword.charAt(i);
                tmp = tmp.append(c);    // 循环创建子节点,tmp临时存储循环的节点元素
            }
            tmp.end = true; // 在最后节点中,手动加结束标志,便于查找到中间返回
            return root;
        }

        // 查找单词
        public boolean search(String keyword) {
            if (keyword == null || keyword == "") {
                return false;
            }
            // 必须正确单词
            Assert.assertTrue(keyword.matches(regex));
            // 默认字典表数据都为小写字母
            keyword = keyword.toLowerCase();
            TreeNode tmp = this;
            int length = keyword.length();
            for (int i = 0; i < length; i++) {
                char c = keyword.charAt(i);
                TreeNode[] leaves = tmp.leaves;
                tmp = leaves[c - 'a'];    // 为相应下标0-25赋值
                if (tmp == null) { // 之前此节点下没有创建元素,没有找到
                    return false;
                }
            }
            // 如果end == true,说明之前构建到这时就结束了。反之要查找的单词不是完整的单词
            return tmp.end;
        }
    }

    @Test
    public void test() {
        // 这是要构建的字典表
        String[] keywords = {"hello", "world", "helloworld"};
        // 循环初始化完成字典表的构建
        TreeNode treeNode = new TreeNode((char) 0);
        for (String keyworld : keywords) {
            treeNode.build(keyworld);
        }
        System.out.println("构建成功,后续开始进行查找");

        Assert.assertTrue(treeNode.search("hello"));
        Assert.assertTrue(treeNode.search("world"));
        Assert.assertTrue(treeNode.search("helloworld"));

        Assert.assertFalse(treeNode.search("hell"));
        Assert.assertFalse(treeNode.search("helo"));
        Assert.assertFalse(treeNode.search("worlda"));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章