国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

這篇具有很好參考價值的文章主要介紹了二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

??1.什么是二叉樹?

??2.滿二叉樹和完全二叉樹

??2.二叉樹的性質(zhì)

??3.二叉樹的創(chuàng)建與遍歷

3.1 創(chuàng)建二叉樹

3.2 前中后序遍歷——遞歸和非遞歸

??4.二叉樹的實現(xiàn)

1??獲取樹中節(jié)點的個數(shù)

2??獲取葉子節(jié)點的個數(shù)

3??獲取第K層節(jié)點的個數(shù)

4??獲取二叉樹的高度

5??檢測值為value的元素是否存在

6??判斷兩棵樹是否相同【leetcod】

7??另一棵樹的子樹【leetcod】

8??翻轉(zhuǎn)二叉樹【leetcod】

??平衡二叉樹【leetcod】

?二叉樹的層序遍歷

二叉樹的分層遍歷【leetcod】

??5.二叉樹的練習(xí)

1??二叉樹遍歷【??途W(wǎng)】

2??二叉樹的最近公共祖先【leetcod】

3??從前序與中序遍歷序列構(gòu)造二叉樹【leetcod】

4??從中序與后序遍歷序列構(gòu)造二叉樹【leetcod】

5??根據(jù)二叉樹創(chuàng)建字符串【leetcod】

6??判斷一棵樹是不是完全二叉樹


?文章來源地址http://www.zghlxwxcb.cn/news/detail-447140.html

??1.什么是二叉樹?

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

結(jié)點的度:一個結(jié)點含有子樹的個數(shù)稱為該結(jié)點的度; 如上圖:A的度為2

樹的度:一棵樹中,所有結(jié)點度的最大值稱為樹的度; 如上圖:樹的度為2

葉子結(jié)點或終端結(jié)點:度為0的結(jié)點稱為葉結(jié)點; 如上圖:H、I、J、K、G等節(jié)點為葉結(jié)點

雙親結(jié)點或父結(jié)點:若一個結(jié)點含有子結(jié)點,則這個結(jié)點稱為其子結(jié)點的父結(jié)點; 如上圖:A是B的父結(jié)點

孩子結(jié)點或子結(jié)點:一個結(jié)點含有的子樹的根結(jié)點稱為該結(jié)點的子結(jié)點; 如上圖:B是A的孩子結(jié)點

根結(jié)點:一棵樹中,沒有雙親結(jié)點的結(jié)點;如上圖:A

結(jié)點的層次:從根開始定義起,根為第1層,根的子結(jié)點為第2層,以此類推

樹的高度或深度:樹中結(jié)點的最大層次; 如上圖:樹的高度為4

??一棵二叉樹是結(jié)點的一個有限集合,該集合:

1??或者為空 2??或者是由一個根節(jié)點加上兩棵別稱為左子樹右子樹的二叉樹組成。

?對于二叉樹來說:每一個節(jié)點的度不能大于2,并且二叉樹是一個有序樹

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

??2.滿二叉樹和完全二叉樹

滿二叉樹: 一棵二叉樹,如果每層的結(jié)點數(shù)都達到最大值,則這棵二叉樹就是滿二叉樹。也就是說,如果一棵二叉樹的層數(shù)為K,且結(jié)點總數(shù)是 2^k - 1,第k層節(jié)點數(shù)是 2^(k-1) ,則它就是滿二叉樹。如果一共有n個節(jié)點,那么k=log2(n+1)

完全二叉樹(最小深度: 完全二叉樹是效率很高的數(shù)據(jù)結(jié)構(gòu),完全二叉樹是由滿二叉樹而引出來的。對于深度為K的,有n個結(jié)點的二叉樹,當且僅當其每一個結(jié)點都與深度為K的滿二叉樹中編號從0至n-1的結(jié)點一一對應(yīng)時稱之為完全二叉樹。 要注意的是滿二叉樹是一種特殊的完全二叉樹?!?strong>從左往右不可以空結(jié)點

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

??2.二叉樹的性質(zhì)

1??一顆 N 節(jié)點的樹有 N - 1 條邊

2??若規(guī)定根結(jié)點的層數(shù)為1,則一棵非空二叉樹的第i層上最多有 2^i - 1(i>0)個結(jié)點

3??若規(guī)定只有根結(jié)點的二叉樹的深度為1,則深度為K的二叉樹的最大結(jié)點數(shù)是? 2^k - 1?(k>=0)

4??具有n個結(jié)點的完全二叉樹的深度klog2(n+1)?上取整

5??對任何一棵二叉樹, 如果其葉結(jié)點個數(shù)為 n0, 度為2的非葉結(jié)點個數(shù)為 n2,則有n0=n2+1 (度為0的節(jié)點是度為2的節(jié)點多1個)

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

?6??偶數(shù)個結(jié)點的完全二叉樹:度為1的結(jié)點個數(shù)為1;奇數(shù)個結(jié)點的完全二叉樹:度為1的結(jié)點個數(shù)為0;

7??對于具有n個結(jié)點的完全二叉樹,如果按照從上至下從左至右的順序?qū)λ泄?jié)點從0開始編號,則對于序號為i的結(jié)點有

若i>0, 雙親序號: (i-1)/2; i=0 , i 為根結(jié)點編號,無雙親結(jié)點
2i+1<n ,左孩子序號: 2i+1 ,否則無左孩子
2i+2<n ,右孩子序號: 2i+2 ,否則無右孩子

已知父親結(jié)點下標是i:

左孩子:2*i+1? ?右孩子:2*i+2

已知孩子結(jié)點下標是i:

父親結(jié)點下標:(i-1)/2

??3.二叉樹的創(chuàng)建與遍歷

3.1 創(chuàng)建二叉樹

?對于一個二叉樹,我們定義一個數(shù)據(jù)域、左孩子域、右孩子域、根結(jié)點。對于一個二叉樹,如圖所示,總會有一個左結(jié)點和右結(jié)點(可以為null)

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    //創(chuàng)建二叉樹
    public class TreeNode {
        public char val;//數(shù)據(jù)域
        public TreeNode left;//左孩子的引用
        public TreeNode right;//右孩子的引用

        //構(gòu)造函數(shù)
        public TreeNode(char val) {
            this.val = val;
        }
    }

    public TreeNode root;//二叉樹的根結(jié)點

    public TreeNode createTree() {
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        E.right = H;
        this.root = A;
        return root;
    }

3.2 前中后序遍歷——遞歸和非遞歸

遍歷:(Traversal)是指沿著某條搜索路線,依次對樹中每個結(jié)點均做一次且僅做一次訪問。訪問結(jié)點所做的操作依賴于具體的應(yīng)用問題(比如:打印節(jié)點內(nèi)容、節(jié)點內(nèi)容加1)。

1??前序遍歷(Preorder Traversal 亦稱先序遍歷)——訪問根結(jié)點--->根的左子樹--->根的右子樹

?注意:每棵樹都有根、左、右結(jié)點。并且這里邊每個結(jié)點都可以作為孩子結(jié)點的根結(jié)點

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    //前序遍歷  遞歸
    public void preOrder(TreeNode root) {
        if(root == null) {
            return;
        }
        System.out.println(root.val + " ");//先打印再遞歸
        preOrder(root.left);
        preOrder(root.right);
    }

非遞歸實現(xiàn)二叉樹的前序遍歷:使用棧完成——定義一個cur = root,把根節(jié)點放入棧中,同時進行打印,把根左邊放入棧中,再進行打印,繼續(xù)往左邊走放入棧中,再進行打??;再往左邊走,如果為null,則從棧中彈出這個元素給top;如果這個元素右邊為null,則再彈出一個元素給top,循環(huán)以上過程

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    /非遞歸:    
    public void preOrderNor(TreeNode root) {
        if(root == null) {
            return;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.val + " ");
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            cur = top.right;
        }
        System.out.println();
    }

2??中序遍歷(Inorder Traversal)——根的左子樹--->根節(jié)點--->根的右子樹。

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

?

    //中序遍歷
    public void inOrder(TreeNode root) {
        if(root == null) {
            return;
        }
        inOrder(root.left);
        System.out.println(root.val + " ");
        inOrder(root.right);
    }
    //中序遍歷非遞歸
    public void inOrderNor(TreeNode root) {
        if(root == null) {
            return;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            System.out.print(top.val + " ");
            cur = top.right;
        }
        System.out.println();
    }

3??后序遍歷(Postorder Traversal)——根的左子樹--->根的右子樹--->根節(jié)點

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    //后序遍歷
    public void postOrder(TreeNode root) {
        if(root == null) {
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.println(root.val + " ");
    }
    //后序遍歷非遞歸
    public void postOrderNor(TreeNode root) {
        if(root == null) {
            return;
        }
        TreeNode cur = root;
        TreeNode prev = null;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.peek();
            if(top.right == null || top.right == prev) {
                System.out.print(top.val+" ");
                stack.pop();
                prev = top;
            }else {
                cur = top.right;
            }
        }
        System.out.println();
    }

??4.二叉樹的實現(xiàn)

1??獲取樹中節(jié)點的個數(shù)

??左樹的結(jié)點 + 右樹的結(jié)點 + 1? ? ? ? ? ? ?遍歷思路:遇到結(jié)點就+1

    //子問題思路:
    public int size(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftSize = size(root.left);
        int rightSize = size(root.right);
        return leftSize + rightSize + 1;
    }
    //遍歷思路:
    public  int nodeSize;//靜態(tài)成員變量
    public void size2(TreeNode root) {
        if(root == null) {
            return ;
        }
        nodeSize++;
        size2(root.left);
        size2(root.right);
    }

2??獲取葉子節(jié)點的個數(shù)

??左樹的葉子結(jié)點 + 右樹的結(jié)點? ? ? ?

    // 獲取葉子節(jié)點的個數(shù)——子問題思路
    int getLeafNodeCount(TreeNode root) {
        if(root == null) {
            return 0;
        }
        if(root.left == null && root.right == null){
            return 1;
        }
        int leftSize = getLeafNodeCount(root.left);
        int rightSize = getLeafNodeCount(root.right);
        return leftSize+rightSize;
    }
    // 獲取葉子節(jié)點的個數(shù)——遍歷思路
    public int leafSize;
    void getLeafNodeCount2(TreeNode root) {
        if(root == null) {
            return ;
        }
        if(root.left == null && root.right == null){
            leafSize++;
        }
        getLeafNodeCount2(root.left);
        getLeafNodeCount2(root.right);
    }

3??獲取第K層節(jié)點的個數(shù)

??左樹的第k-1層? +? 右樹的第k-1層(對于root來說是第k層)

    // 獲取第K層節(jié)點的個數(shù)
    int getKLevelNodeCount(TreeNode root,int k) {
        if(root == null) {
            return 0;
        }
        if(k == 1) {
            return 1;
        }
        int leftSize = getKLevelNodeCount(root.left,k-1);
        int rightSize = getKLevelNodeCount(root.right,k-1);
        return leftSize+rightSize;
    }

4??獲取二叉樹的高度

??左樹的高度和右樹的高度的最大值+1

    public int getHeight(TreeNode root) {
        if(root == null) {
            return 0;
        }

        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);

        return (leftHeight > rightHeight) ? (leftHeight+1) : (rightHeight+1);
    }

5??檢測值為value的元素是否存在

??遍歷二叉樹,是否存在value的元素——前序

    // 檢測值為value的元素是否存在
    TreeNode find(TreeNode root, int val) {
        if(root == null) {
            return null;
        }
        if(root.val == val) {
            return root;
        }
        TreeNode leftTree = find(root.left,val);//左子樹第一個元素為新的root,開始尋找value
        //如果沒有找到,繼續(xù)遞歸;如果找到返回上一層直到返回這個值;如果左子樹沒有找到返回空
        if(leftTree != null) {
            return leftTree;
        }
        TreeNode rightTree = find(root.right,val);
        if(rightTree != null) {
            return rightTree;
        }
        return null;//沒有找到
    }

6??判斷兩棵樹是否相同【leetcod】

??leetcod題目:給你兩棵二叉樹的根節(jié)點 p 和 q ,編寫一個函數(shù)來檢驗這兩棵樹是否相同。如果兩個樹在結(jié)構(gòu)上相同,并且節(jié)點具有相同的值,則認為它們是相同的。

??題目鏈接:相同的樹

??做題思路:判斷根,左子樹、右子樹是否相同——1.判斷結(jié)構(gòu)是否相同? ? ?2.判斷val是否相同

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    /**
     * 時間復(fù)雜度:O(min(m,n)),其中 m 和 n 分別是兩個二叉樹的節(jié)點數(shù)。
     * 兩個二叉樹同時進行深度優(yōu)先搜索,只有當兩個二叉樹中的對應(yīng)節(jié)點都不為空時才會訪問到該節(jié)點,因此被訪問到的節(jié)點數(shù)不會超過較小的二叉樹節(jié)點數(shù)
     * 空間復(fù)雜度:O(min(m,n)),其中 m 和 n 分別是兩個二叉樹的節(jié)點數(shù)。
     * 空間復(fù)雜度取決于遞歸調(diào)用的層數(shù),遞歸調(diào)用的層數(shù)不會超過較小的二叉樹的最大高度,最壞情況下,二叉樹的高度等于節(jié)點數(shù)。
     * @param p
     * @param q
     * @return
     */
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p == null && q != null || p != null && q == null) {
            return false;
        }
        //走到這里 要么都是空 要么都不是空
        if(p == null && q == null) {
            return true;
        }
        if(p.val != q.val) {
            return false;
        }
        //p q都不空 且 值一樣
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }

7??另一棵樹的子樹【leetcod】

??leetcod題目:給你兩棵二叉樹?root?和?subRoot?。檢驗?root?中是否包含和?subRoot?具有相同結(jié)構(gòu)和節(jié)點值的子樹。如果存在,返回?true?;否則,返回?false?。二叉樹?tree?的一棵子樹包括?tree?的某個節(jié)點和這個節(jié)點的所有后代節(jié)點。tree?也可以看做它自身的一棵子樹。

??題目鏈接:另一棵樹的子樹

??做題思路:1.是不是相同的樹? ? 2.是不是root的左子樹? 3.是不是root的右子樹

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root == null || subRoot == null) {
            return false;
        }
        if(isSameTree(root,subRoot)) return true;
        if(isSubtree(root.left,subRoot)) return true;
        if(isSubtree(root.right,subRoot)) return true;
        return false;
    }

    //判斷相同的樹
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p != null && q == null || p == null && q != null) {
            return false;
        }
        if(p == null && q == null) {
            return true;
        }
        if(p.val != q.val) {
            return false;
        }
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }

8??翻轉(zhuǎn)二叉樹【leetcod】

??leetcod題目:給你一棵二叉樹的根節(jié)點?root?,翻轉(zhuǎn)這棵二叉樹,并返回其根節(jié)點。

??題目鏈接:翻轉(zhuǎn)二叉樹

??做題思路:

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    public TreeNode invertTree(TreeNode root) {
        if(root == null) {
            return null;
        }
        //交換左右結(jié)點
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        invertTree(root.left);//左樹遞歸
        invertTree(root.right);//右樹遞歸

        return root;
    }

9??平衡二叉樹【leetcod】

??leetcod題目:給定一個二叉樹,判斷它是否是高度平衡的二叉樹。本題中,一棵高度平衡二叉樹定義為:一個二叉樹每個節(jié)點 的左右兩個子樹的高度差的絕對值不超過 1 。

??題目鏈接:平衡二叉樹

??做題思路:1.求整棵樹的高度? ? 2.左樹高度和右樹高度的絕對值之差小于2

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    /**
     * 時間復(fù)雜度:O(N^2)——每個結(jié)點都需要求高度
     * @param root
     * @return
     */
    public boolean isBalanced(TreeNode root) {
        if(root == null) {
            return true;
        }
        //求左樹和右樹的高度
        int leftH = getHeight(root.left);
        int rightH = getHeight(root.right);
        //左樹和右樹絕對值之差小于2
        return Math.abs(leftH-rightH) < 2 && isBalanced(root.left) &&isBalanced(root.right);
    }

    // 獲取二叉樹的高度
    public int getHeight(TreeNode root) {
        if(root == null) {
            return 0;
        }

        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);

        return (leftHeight > rightHeight) ? (leftHeight+1) : (rightHeight+1);
    }
    /**
     * 時間復(fù)雜度:O(N)——求高度的過程中就判斷是否平衡
     * @param root
     * @return
     */
    public boolean isBalanced2(TreeNode root) {
        return maxDepth2(root) >= 0;
    }

    public int maxDepth2(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftHeight = maxDepth2(root.left);
        if(leftHeight < 0) return -1;

        int rightHeight = maxDepth2(root.right);
        if(rightHeight < 0) return -1;

        if(Math.abs(leftHeight-rightHeight) <= 1) {
            return Math.max(leftHeight,rightHeight)+1;
        }else {
            return -1;
        }
    }

??平衡二叉樹【leetcod】

??leetcod題目:給你一個二叉樹的根節(jié)點?root?, 檢查它是否軸對稱。

??題目鏈接:平衡二叉樹

??做題思路:判斷整棵樹是不是抽對稱的——判斷左子樹和右子樹是不是對稱的——左子樹的左樹和右子樹的右樹、左子樹的右樹和右子樹的左樹

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    public boolean isSymmetric(TreeNode root) {
        if(root == null) {
            return true;
        }
        return isSymmetricChild(root.left,root.right);
    }

    public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree) {
        if(leftTree != null && rightTree == null || leftTree == null && rightTree != null) {
            return false;
        }
        if(leftTree == null && rightTree == null) {
            return true;
        }
        if(leftTree.val != rightTree.val) {
            return false;
        }
        return isSymmetricChild(leftTree.left,rightTree.right) && isSymmetricChild(leftTree.right,rightTree.left);
    }

?二叉樹的層序遍歷

??做題思路:使用隊列進行遍歷:定義一個cur——從根結(jié)點出發(fā),放入隊列中,判斷隊列是否為空,不為空彈出隊列的第一個元素,放入cur然后打??;然后把cur的左邊和右邊放入隊列中,判斷隊列是否為空,不為空再彈出隊列的隊頭(每次彈出1個元素),再放入cur中打印。一直循環(huán)直到遍歷完成結(jié)束

    //二叉樹的層序遍歷
    public void levelOrder(TreeNode root) {
        if(root == null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            TreeNode cur = queue.poll();//不等于空,彈出
            System.out.println(cur.val + " ");
            if(cur.left != null) {
                queue.offer(cur.left);
            }
            if(cur.right != null) {
                queue.offer(cur.right);
            }
        }
    }

二叉樹的分層遍歷【leetcod】

??leetcod題目:給你二叉樹的根節(jié)點?root?,返回其節(jié)點值的?層序遍歷?。 (即逐層地,從左到右訪問所有節(jié)點)

??題目鏈接:二叉樹的分層遍歷

??做題思路:每一層都是一個集合——得確定哪一層有哪些結(jié)點:如果隊列不等于空,求當前隊列的長度,這次彈出元素為當前隊列長度的元素

    public List<List<Integer>> levelOrder2(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        if(root == null) {
            return list;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            while (size != 0) {
                TreeNode cur = queue.poll();
                //System.out.print(cur.val + " ");
                tmp.add(cur.val);
                size--;
                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            list.add(tmp);
        }
        return list;
    }

??5.二叉樹的練習(xí)

1??二叉樹遍歷【??途W(wǎng)】

????途W(wǎng)題目:編一個程序,讀入用戶輸入的一串先序遍歷字符串,根據(jù)此字符串建立一個二叉樹(以指針方式存儲)。 例如如下的先序遍歷字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空樹。建立起此二叉樹以后,再對二叉樹進行中序遍歷,輸出遍歷結(jié)果。

輸入描述:輸入包括1行字符串,長度不超過100。

輸出描述:可能有多組測試數(shù)據(jù),對于每組數(shù)據(jù), 輸出將輸入字符串建立二叉樹后中序遍歷的序列,每個字符后面都有一個空格。 每個輸出結(jié)果占一行

輸入:abc##de#g##f###? ? ? ? ? 輸出:c b e g d f a

??題目鏈接:二叉樹遍歷

???做題思路:

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

class TreeNode {
    public char val;//數(shù)據(jù)域
    public TreeNode left;//左孩子的引用
    public TreeNode right;//右孩子的引用

    //構(gòu)造函數(shù)
    public TreeNode(char val) {
         this.val = val;
    }
}

// 注意類名必須為 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的區(qū)別
        while(in.hasNextLine()) {
            String str =  in.nextLine();//讀字符串放入str中
            TreeNode root = createTree(str);
            inorder(root);
        }

    }

    public static int i = 0;


    //讀到字符串,緊接著來創(chuàng)造二叉樹
    public static TreeNode createTree(String str) {
        TreeNode root = null;
        if(str.charAt(i) != '#') {//查看i下標的值是字符還是#
            root = new TreeNode(str.charAt(i));//創(chuàng)建一個節(jié)點為根
            i++;
            root.left = createTree(str);
            root.right = createTree(str);
        }else {
            i++;//如果為#,則繼續(xù)往后走一格
        }
        return root;
        //1.如果為#,則繼續(xù)往后走一格,返回上一層遞歸返回root
        //2.如果根的左邊和右邊都為空,則返回當前根給上一層
    }

    //中序遍歷
    public static void inorder(TreeNode root) {
        if(root == null) {
            return;
        }
        inorder(root.left);
        System.out.print(root.val + " ");
        inorder(root.right);
    }
}

2??二叉樹的最近公共祖先【leetcod】

??leetcod題目:給定一個二叉樹, 找到該樹中兩個指定節(jié)點的最近公共祖先。最近公共祖先的定義為:“對于有根樹 T 的兩個節(jié)點 p、q,最近公共祖先表示為一個節(jié)點 x,滿足 x 是 p、q 的祖先且 x 的深度盡可能大(一個節(jié)點也可以是它自己的祖先)。”

??題目鏈接:二叉樹的最近公共祖先

???做題思路:1.p、q要么在跟的左右兩邊、2.要么是根的左邊 或者 右邊、3.其中一個節(jié)點是公共祖先

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) {
            return null;
        }
        //判斷根結(jié)點是不是其中一個公共結(jié)點
        if(root == p || root == q) {
            return root;
        }
        TreeNode leftRet = lowestCommonAncestor(root.left,p,q);//去root的左邊找p、q
        TreeNode rightRet = lowestCommonAncestor(root.right,p,q);//去root的右邊找p、q

        if(leftRet != null && rightRet != null) {//root的左邊和右邊不為空即返回root——1.root為根 2.root為左邊根
            return root;
        }else if(leftRet != null) {
            return leftRet;
        }else if(rightRet != null) {
            return rightRet;
        }
        return null;
    }

第二種 ——??做題思路:如果每個結(jié)點有了父親結(jié)點的地址,那么這個題就變成了求相交結(jié)點——此時我們可以使用棧

從根結(jié)點到指定的p、q路徑上的所有結(jié)點放入不同的兩個棧中,求棧中元素的個數(shù)差,哪個棧多幾個元素,就讓哪個棧中彈出個數(shù)差的元素;之后讓每個棧中都彈出一個元素比較兩個元素是否相同,如果相同則為公共結(jié)點

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

???難點: 如何把從根節(jié)點到指定節(jié)點,路徑上的所有節(jié)點找到,放入棧里邊?怎么知道這個節(jié)點要彈出去?

??:從根節(jié)點開始放入第一個棧中,從根節(jié)點的左邊開始,每個元素放入棧中,直到某個元素的左邊和右邊為null,彈出這個元素,然后從這個元素的右邊去找,找不到則彈出此元素,直到找到為止

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    /**
     *  找到從根節(jié)點到指定節(jié)點node路徑上的所有的節(jié)點,存放到棧當中
     * @param root
     * @param node
     * @param stack
     * @return
     */
    //找p、q節(jié)點
    public boolean getPath(TreeNode root, TreeNode node, Deque<TreeNode> stack) {
        if(root == null || node == null) {
            return false;
        }
        stack.push(root);
        //放完之后  要檢查
        if(root == node) {
            return true;
        }
        boolean ret1 = getPath(root.left,node,stack);
        if(ret1) {
            return true;
        }
        boolean ret2 = getPath(root.right,node,stack);
        if(ret2) {
            return true;
        }
        stack.pop();//如果沒有找到,彈出這個元素,返回上一層
        return false;
    }

    
    public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) {
        //1、兩個棧當中 存儲好數(shù)據(jù)
        Deque<TreeNode> stack1 = new LinkedList<>();//第一個棧
        getPath(root,p,stack1);
        Deque<TreeNode> stack2 = new LinkedList<>();//第二個棧
        getPath(root,q,stack2);
        //2.判斷棧的大小
        int size1 = stack1.size();
        int size2 = stack2.size();
        if(size1 > size2) {
            int size = size1 - size2;
            while(size != 0) {
                stack1.pop();//彈出元素,直到size為0;
                size--;
            }
        }else {
            int size = size2 - size1;
            while(size != 0) {
                stack2.pop();//彈出元素,直到size為0;
                size--;
            }
        }
        //此時棧里面數(shù)據(jù)的個數(shù) 是一樣的
        while(!stack1.isEmpty() && !stack2.isEmpty()) {
            if(stack1.peek() != stack2.peek()) {//查看棧頂元素是否相同
                //不同彈出棧頂元素
                stack1.pop();
                stack2.pop();
            }else {
                return stack1.peek();//相同返回這個元素,即為公共節(jié)點
            }
        }
        return null;

    }

3??從前序與中序遍歷序列構(gòu)造二叉樹【leetcod】

??leetcod題目:給定兩個整數(shù)數(shù)組?preorder?和?inorder?,其中?preorder?是二叉樹的先序遍歷,?inorder?是同一棵樹的中序遍歷,請構(gòu)造二叉樹并返回其根節(jié)點。

??題目鏈接:從前序與中序遍歷序列構(gòu)造二叉樹

???做題思路:1.根據(jù)前序遍歷找到根? ? ? ??2.在中序遍歷當中,找到根的位置

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

    public int i = 0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }
    public TreeNode buildTreeChild(int[] preorder,int[] inorder,int inbegin,int inend) {
        if(inbegin > inend) {
            return null;//沒有子樹了
        }
        TreeNode root = new TreeNode(preorder[i]);

        //找到當前根,在中序遍歷的位置
        int rootIndex = findIndex(inorder,inbegin,inend,preorder[i]);//在inbegin和inend尋找preorder[i]
        //找打根之后,左邊就是左樹,右邊就是右樹
        i++;
        //此時的根左邊——開始位置沒有變,結(jié)束位置為找到根位置-1,即rootIndex-1
        root.left = buildTreeChild(preorder,inorder,inbegin,rootIndex-1);
        //此時的根右邊——開始位置為rootIndex+1,結(jié)束位置沒有變
        root.right = buildTreeChild(preorder,inorder,rootIndex+1,inend);

        return root;
    }
    //在中序遍歷當中尋找這個元素
    private int findIndex(int[] inorder,int inbegin, int inend, int key) {
        for(int i = inbegin; i <= inend; i++) {
            if(inorder[i] == key) {
                return i;
            }
        }
        return -1;
    }

4??從中序與后序遍歷序列構(gòu)造二叉樹【leetcod】

??leetcod題目:給定兩個整數(shù)數(shù)組?inorder?和?postorder?,其中?inorder?是二叉樹的中序遍歷,?postorder?是同一棵樹的后序遍歷,請你構(gòu)造并返回這顆?二叉樹?。

??題目鏈接:從中序與后序遍歷序列構(gòu)造二叉樹

???做題思路:此題做題思路和上一題大致一樣,但是有一點小問題,就是從后序遍歷的結(jié)尾開始往前走,先創(chuàng)建右樹,再創(chuàng)建左樹

前序遍歷:根、左、右? ? ? ? ? ? ?后序遍歷:左、右、根

public int i = 0;
    public TreeNode buildTree1(int[] inorder, int[] postorder) {
        i = postorder.length-1;//從最后開始
        return buildTreeChild2(postorder,inorder,0,inorder.length-1);
    }

    public TreeNode buildTreeChild2(int[] postorder, int[] inorder,
                                    int inbegin,int inend) {
        if(inbegin > inend) {
            return null;//沒有子樹了
        }
        TreeNode root = new TreeNode(postorder[i]);
        //找到當前根,在后序遍歷的位置
        int rootIndex = findIndex1(inorder,inbegin,inend,postorder[i]);
        //找打根之后,左邊就是左樹,右邊就是右樹
        i--;
        //此時的根右邊——開始位置為rootIndex+1,結(jié)束位置沒有變
        root.right = buildTreeChild2(postorder,inorder,rootIndex+1,inend);
        //此時的根左邊——開始位置沒有變,結(jié)束位置為找到根位置-1,即rootIndex-1
        root.left = buildTreeChild2(postorder,inorder,inbegin,rootIndex-1);
        return root;
    }
    //在后序遍歷當中尋找這個元素
    private int findIndex1( int[] inorder,int inbegin,int inend, int key) {
        for(int i = inbegin;i <= inend; i++) {
            if(inorder[i] == key) {
                return i;
            }
        }
        return -1;
    }

5??根據(jù)二叉樹創(chuàng)建字符串【leetcod】

??leetcod題目:給你二叉樹的根節(jié)點?root?,請你采用前序遍歷的方式,將二叉樹轉(zhuǎn)化為一個由括號和整數(shù)組成的字符串,返回構(gòu)造出的字符串。

空節(jié)點使用一對空括號對?"()"?表示,轉(zhuǎn)化后需要省略所有不影響字符串與原始二叉樹之間的一對一映射關(guān)系的空括號對。

輸入:root = [1,2,3,4] 輸出:"1(2(4))(3)" 解釋:初步轉(zhuǎn)化后得到 "1(2(4)())(3()())" ,但省略所有不必要的空括號對后,字符串應(yīng)該是"1(2(4))(3)"

??題目鏈接:根據(jù)二叉樹創(chuàng)建字符串

???做題思路:

    public String tree2str(TreeNode root) {
        if(root == null) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder();
        tree2strChilde(root,stringBuilder);

        return stringBuilder.toString();
    }
    public void tree2strChilde(TreeNode t,StringBuilder stringBuilder) {

        if (t == null) {
            return;
        }

        stringBuilder.append(t.val);
        if (t.left != null) {
            stringBuilder.append("(");
            tree2strChilde(t.left, stringBuilder);
            stringBuilder.append(")");
        } else {
            //左邊為空了
            if (t.right != null) {
                //右邊不為空
                stringBuilder.append("()");
            } else {
                //右邊為空
                return;
            }
        }

        if (t.right == null) {
            return;
        } else {
            stringBuilder.append("(");
            tree2strChilde(t.right, stringBuilder);
            stringBuilder.append(")");
        }
    }

6??判斷一棵樹是不是完全二叉樹

??做題思路:使用隊列完成——把根放入隊列當中,如果隊列不為空,彈出一個元素給cur,不管左邊、右邊是否為空,把左子樹和右子樹都放入隊列中(如果為空,放入null),如果隊列不為空,繼續(xù)彈出一個元素給cur,循環(huán),直到cur里邊放入null。這是隊列中如果不為空,則不是二叉樹,如果為空,則為二叉樹

二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】

?

    boolean isCompleteTree(TreeNode root){
        if(root == null) {
            return true;
        }
        //創(chuàng)建隊列
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if(cur != null) {
                queue.offer(cur.left);
                queue.offer(cur.right);
            }else {
                break;
            }
        }
        while (!queue.isEmpty()) {
            TreeNode tmp = queue.poll();
            if(tmp != null) {
                return false;
            }
        }
        return true;
    }

?

?

?

到了這里,關(guān)于二叉樹【數(shù)據(jù)結(jié)構(gòu)】【超詳細,一學(xué)就會】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)之線索二叉樹詳細解釋

    數(shù)據(jù)結(jié)構(gòu)之線索二叉樹詳細解釋

    1.1 線索二叉樹的原理 我們現(xiàn)在倡導(dǎo)節(jié)約型社會,一切都應(yīng)該以節(jié)約為本。但當我們創(chuàng)建二叉樹時我們會發(fā)現(xiàn)其中一共有兩個指針域,有的指針域指向的結(jié)構(gòu)為空,這也就浪費了很多空間。所以為了不去浪費這些空間我們采取了一個措施。就是利用那些空地址,存放指向結(jié)點

    2023年04月20日
    瀏覽(20)
  • 【數(shù)據(jù)結(jié)構(gòu)】—搜索二叉樹(C++實現(xiàn),超詳細?。? decoding=

    【數(shù)據(jù)結(jié)構(gòu)】—搜索二叉樹(C++實現(xiàn),超詳細!)

    ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????????????? ?? 慕斯主頁 : 修仙—別有洞天 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????? ?? 今日夜電波 :消えてしまいそうです—真夜中 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    2024年02月05日
    瀏覽(24)
  • 數(shù)據(jù)結(jié)構(gòu)進階篇 之 【二叉樹】詳細概念講解(帶你認識何為二叉樹及其性質(zhì))

    數(shù)據(jù)結(jié)構(gòu)進階篇 之 【二叉樹】詳細概念講解(帶你認識何為二叉樹及其性質(zhì))

    有朋自遠方來,必先苦其心志,勞其筋骨,餓其體膚,空乏其身,鞭數(shù)十,驅(qū)之別院 1.1 二叉樹中組分構(gòu)成名詞概念 1.2 二叉樹的結(jié)構(gòu)概念 1.3 特殊的二叉樹 2.1 順序存儲 2.2 鏈式存儲 前言: 在你的想象中如果有一個“二叉樹”會是什么樣子呢? 顧名思義,現(xiàn)實中的二叉樹我們

    2024年04月13日
    瀏覽(24)
  • 【數(shù)據(jù)結(jié)構(gòu)】二叉樹中的遞歸問題(超詳細畫圖~)

    【數(shù)據(jù)結(jié)構(gòu)】二叉樹中的遞歸問題(超詳細畫圖~)

    和光同塵_我的個人主頁 不管風(fēng)吹浪打,勝似閑庭信步。 --毛澤東 我本來還說上節(jié)難來著,沒想到這節(jié)更難?? 不過我既然會了保證xdm也能看懂?? 首先回顧下二叉樹的概念 二叉樹是由:空樹 或者非空樹(根節(jié)點,根節(jié)點的左子樹、根節(jié)點的右子樹)組成的 從概念中可以看出

    2024年02月07日
    瀏覽(31)
  • 數(shù)據(jù)結(jié)構(gòu)初階之二叉樹的詳細解析

    數(shù)據(jù)結(jié)構(gòu)初階之二叉樹的詳細解析

    個人主頁:點我進入主頁 專欄分類:C語言初階? ? ??C語言程序設(shè)計————KTV? ? ? ?C語言小游戲? ? ?C語言進階 C語言刷題? ? ? ?數(shù)據(jù)結(jié)構(gòu)初階? ??Linux 歡迎大家點贊,評論,收藏。 一起努力,共赴大廠。 目錄 1.前言? 2.二叉樹各個功能代碼實現(xiàn) 2.1二叉樹結(jié)構(gòu)體 2.2二叉

    2024年02月05日
    瀏覽(26)
  • 數(shù)據(jù)結(jié)構(gòu)之二叉樹(C語言附詳細代碼)

    數(shù)據(jù)結(jié)構(gòu)之二叉樹(C語言附詳細代碼)

    目錄 一,樹和二叉樹 1.樹 ①定義 ②關(guān)于樹的一些概念 2.二叉樹 ①定義 ②特殊的二叉樹 ③二叉樹的性質(zhì) ④二叉樹的存儲結(jié)構(gòu)(順序結(jié)構(gòu),只適用于完全二叉樹) ⑤二叉樹的遍歷 二,二叉樹操作代碼 1.頭文件 2.函數(shù)代碼 ①創(chuàng)建二叉樹 ②前序遍歷二叉樹 ③中序遍歷二叉樹 ④后序

    2024年02月01日
    瀏覽(25)
  • 【數(shù)據(jù)結(jié)構(gòu)】二叉樹的創(chuàng)建和四種遍歷(附帶詳細注釋)

    【數(shù)據(jù)結(jié)構(gòu)】二叉樹的創(chuàng)建和四種遍歷(附帶詳細注釋)

    《數(shù)據(jù)結(jié)構(gòu)系列首頁》是數(shù)據(jù)結(jié)構(gòu)系列文章的首頁,其中會 逐步更新 各種數(shù)據(jù)結(jié)構(gòu)的實現(xiàn),有興趣的選手可以一看。 首頁中不僅有各種數(shù)據(jù)結(jié)構(gòu)的實現(xiàn),還有學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu) 必備的基礎(chǔ)知識 ,如果有選手覺得自己的基礎(chǔ)不太牢固,可以先將搞定基礎(chǔ)知識,之后再攻克數(shù)據(jù)結(jié)

    2024年02月05日
    瀏覽(18)
  • 【數(shù)據(jù)結(jié)構(gòu)】二叉樹遍歷的實現(xiàn)(超詳細解析,小白必看系列)

    【數(shù)據(jù)結(jié)構(gòu)】二叉樹遍歷的實現(xiàn)(超詳細解析,小白必看系列)

    目錄 一、前言 ??為何使用鏈式二叉樹? ???何為鏈式二叉樹 ???二叉樹的構(gòu)建 ??創(chuàng)建二叉鏈結(jié)構(gòu) ??手動構(gòu)建一顆樹? ??二叉樹的遍歷 (重點) ??前序遍歷 ???中序遍歷 ???后續(xù)遍歷 ???二叉樹的經(jīng)典問題(重點) ??二叉樹節(jié)點個數(shù) ???二叉樹葉子節(jié)點的個數(shù) ???

    2024年02月02日
    瀏覽(19)
  • 十三、數(shù)據(jù)結(jié)構(gòu)——二叉樹的遍歷(先序、中序和后序)詳細思路和代碼

    十三、數(shù)據(jù)結(jié)構(gòu)——二叉樹的遍歷(先序、中序和后序)詳細思路和代碼

    在數(shù)據(jù)結(jié)構(gòu)中,二叉樹是一種常用且重要的數(shù)據(jù)結(jié)構(gòu)。二叉樹的遍歷是指按照一定順序訪問二叉樹的所有節(jié)點,常見的遍歷方式有前序遍歷、中序遍歷和后序遍歷。本文將詳細介紹這三種遍歷算法,并介紹最優(yōu)二叉樹。 首先,我們先來了解一下二叉樹的基本定義。二叉樹是每

    2024年02月15日
    瀏覽(24)
  • 數(shù)據(jù)結(jié)構(gòu)之進階二叉樹(二叉搜索樹和AVL樹、紅黑樹的實現(xiàn))超詳細解析,附實操圖和搜索二叉樹的實現(xiàn)過程圖

    數(shù)據(jù)結(jié)構(gòu)之進階二叉樹(二叉搜索樹和AVL樹、紅黑樹的實現(xiàn))超詳細解析,附實操圖和搜索二叉樹的實現(xiàn)過程圖

    緒論? “生命有如鐵砧,愈被敲打,愈能發(fā)出火花?!だ浴保槐菊轮饕菙?shù)據(jù)結(jié)構(gòu) 二叉樹的進階知識,若之前沒學(xué)過二叉樹建議看看這篇文章一篇掌握二叉樹,本章的知識從淺到深的 對搜索二叉樹的使用進行了介紹和對其底層邏輯的實現(xiàn)進行了講解 ,希望能對你有所

    2024年02月04日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包