zoukankan      html  css  js  c++  java
  • 数学基础:四、树的应用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"));
        }
    }
    
  • 相关阅读:
    使用数字进行字符遍历
    注意:C++中double的表示是有误差的
    ER模型到关系模型的转换规则
    SQL中查询优化的主要策略
    分解成3NF保持函数依赖且为无损连接的算法
    函数依赖集闭包、属性集闭包、超键、候选键和最小函数依赖集的求法。
    分解成3NF的保持函数依赖的分解算法:
    模式分解是否为无损连接的判断方法
    字符串处理技巧
    sort+结构体实现二级排序
  • 原文地址:https://www.cnblogs.com/dulinan/p/12032996.html
Copyright © 2011-2022 走看看