數學基礎:四、樹的應用2(利用樹結構存儲字典表&深度優先搜索)(優化後:由數組改爲Map)

樹的深度優先搜索那,做了一個圖,方便在入棧出棧那理解。其中往字典表裏插入了這幾個詞:

.build("hello", "你好")
.build("world", "世界")
.build("helloworld", "你好世界")
.build("able", "有能力的")
.build("about", "大約")
.build("above", "在上面")
.build("abroad", "到國外")
.build("active", "積極的")
.build("activity", "活動")

在這裏插入圖片描述
直接上代碼:

public class Lesson12_1 {

    /**
     * @Description: 前綴樹的結點
     */
    class TreeNode {

        public char label;  // 結點的名稱,在前綴樹裏是單個字母
        public HashMap<Character, TreeNode> sons = null; // 使用哈希映射存放子結點。哈希便於確認是否已經添加過某個字母對應的結點。
        public String prefix = null;   // 從樹的根到當前結點這條通路上,全部字母所組成的前綴。例如通路b->o->y,對於字母o結點而言,前綴是b;對於字母y結點而言,前綴是bo
        public String explanation = null;  // 詞條的解釋

        // 初始化結點
        public TreeNode(char l, String pre, String exp) {
            label = l;
            prefix = pre;
            explanation = exp;
            sons = new HashMap<>();
        }

        private TreeNode build(String str, String exp, String pre, TreeNode root) {
            if ("".equals(str)) {
                this.explanation = exp;
                return root;
            }
            // 處理當前字符串的第一個字母
            char c = str.toCharArray()[0];
            TreeNode found = null;

            // 如果字母結點已經存在於當前父結點之下,找出它。否則就新生成一個
            if (this.sons.containsKey(c)) {
                found = this.sons.get(c);
            } else {
                TreeNode son = new TreeNode(c, pre, "");
                this.sons.put(c, son);
                found = son;
            }

            return found.build(str.substring(1), exp, pre + str.substring(0, 1), root);
        }

        public TreeNode build(String str, String exp) {
            return this.build(str, exp, "", this);
        }

        public String search(String str) {
            if ("".equals(str)) {
                return "請輸入非空字符";
            }

            TreeNode found = this;
            char[] chars = str.toCharArray();
            for (char c : chars) {
                if (!found.sons.containsKey(c)) {
                    return "未查到";
                } else {
                    found = found.sons.get(c);
                }
            }

            return "".equals(found.explanation) ? "未查到" : found.explanation;
        }
    }

    // 使用棧來實現深度優先搜索
    public void dfsByStack(TreeNode root) {

        Stack<TreeNode> stack = new Stack<>();
        // 創建堆棧對象,其中每個元素都是TreeNode類型
        stack.push(root);    // 初始化的時候,壓入根結點

        while (!stack.isEmpty()) {  // 只要棧裏還有結點,就繼續下去

            TreeNode node = stack.pop();  // 彈出棧頂的結點

            if (node.sons.size() == 0) {
                // 已經到達葉子結點了,輸出
                System.out.println(node.prefix + node.label);
            } else {
                // 非葉子結點,遍歷它的每個子結點
                node.sons.forEach((key, value) -> stack.push(value));
            }
        }

    }

    @Test
    public void test() {
        TreeNode treeNode = new TreeNode((char) 0, "", "");
        treeNode.build("hello", "你好")
                .build("world", "世界")
                .build("helloworld", "你好世界")
                .build("able", "有能力的")
                .build("about", "大約")
                .build("above", "在上面")
                .build("abroad", "到國外")
                .build("active", "積極的")
                .build("activity", "活動");
        System.out.println("構建詞庫結束,準備查找");

        System.out.println(treeNode.search("hello"));
        System.out.println(treeNode.search("world"));
        System.out.println(treeNode.search("helloworld"));

        System.out.println(treeNode.search("hell"));
        System.out.println(treeNode.search("helo"));
        System.out.println(treeNode.search("worlda"));

        System.out.println("查找結束,準備深度優先搜索");
        dfsByStack(treeNode);
    }
}

這是之前跟代碼時的步驟:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章