最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java數(shù)據(jù)結(jié)構(gòu)二叉樹難點解析

 更新時間:2021年10月25日 15:12:37   作者:pier~呀  
樹是一種重要的非線性數(shù)據(jù)結(jié)構(gòu),直觀地看,它是數(shù)據(jù)元素(在樹中稱為結(jié)點)按分支關系組織起來的結(jié)構(gòu),很象自然界中的樹那樣。樹結(jié)構(gòu)在客觀世界中廣泛存在,如人類社會的族譜和各種社會組織機構(gòu)都可用樹形象表示

前言

本章,我們主要需要了解以下內(nèi)容

  • 什么是線索二叉樹
  • 怎么去把二叉樹線索化
  • 怎么通過線索二叉樹查找某個數(shù)的后繼結(jié)點
  • 二叉樹的查看——二叉樹怎們遍歷

 什么是線索二叉樹

首先我們來了解一下什么是線索二叉樹?

定義:一個二叉樹通過如下的方法“穿起來”:所有原本為空的右(孩子)指針改為指向該節(jié)點在中序序列中的后繼,所有原本為空的左(孩子)指針改為指向該節(jié)點的中序序列的前驅(qū)。

再看一下為什么要有線索二叉樹?

顧名思義,線索二叉樹,肯定是根據(jù)線索查找,查找速度肯定更快。

  • 線索二叉樹能線性地遍歷二叉樹,從而比遞歸的中序遍歷更快。使用線索二叉樹也能夠方便的找到一個節(jié)點的父節(jié)點,這比顯式地使用父親節(jié)點指針或者棧效率更高。這在??臻g有限,或者無法使用存儲父節(jié)點的棧時很有作用(對于通過深度優(yōu)先搜索來查找父節(jié)點而言)。

那線索僅僅是這樣嗎?當然不,我們都是懶的,能等待解決的問題,為什么會去想新的辦法。我們要解決的是:

  • 為了解決無法直接找到該結(jié)點在某種遍歷序列中的前驅(qū)和后繼結(jié)點的問題
  • 但是同時出現(xiàn)了二叉鏈表找左、右孩子困難的問題,即在構(gòu)建線索二叉樹之后,鏈表的原來遍歷方式會出問題。

最后看一下什么線索二叉樹的圖解

在我們的線索二叉樹的書上,基本上都有以下這張圖:

線索二叉樹

大家看到上面這張圖還是有點懵的叭,我們一起看一下我下面手畫的圖

怎么去把二叉樹線索化

哦!在著之前獻給大家提一下,二叉樹的遍歷方式,有這樣的幾種

  • 前序遍歷二叉樹的遞歸定義(根左右)
  • 中序遍歷二叉樹的遞歸定義(左根右)
  • 后續(xù)遍歷二叉樹的遞歸意義(左右根)

本博文主要討論的是中序遍歷
它的中序遍歷結(jié)果就是ABCDE F GHI

中序遍歷

它的中序線索二叉樹遍歷如下

先畫線索二叉樹

在這里插入圖片描述

虛線箭頭為線索指針,對于所有左指針指向空的節(jié)點:將該節(jié)點的左指針指向該節(jié)點在中序遍歷中的上一節(jié)點;對于所有右指針指向空的節(jié)點,將該節(jié)點的右指針指向該節(jié)點在中序遍歷中的下一結(jié)點。最后一個末尾結(jié)點除外。
中序圖解線索二叉樹

線索二叉樹

怎么通過線索二叉樹查找某個數(shù)的后繼結(jié)點

即形成了一個特殊的雙向鏈表,之所以特殊,以F–>E為例,F(xiàn)–>E并不是直接到達,而是通過F–>B–>D–>E間接到達。

我們嘗試用Java去構(gòu)建一顆線索二叉樹叭

先申明,我從未使用Java構(gòu)建過樹,二叉樹都沒有,若有錯誤,請指出

數(shù)據(jù)結(jié)點類

package com.testtree;

/**
 * @author pier
 */
public class TreeNode {
    /**數(shù)據(jù)域**/
    private int data;
    /**左指針**/
    private TreeNode left;
    /** 左孩子是否為線索,采用布爾類型主要是判斷是否未null足以**/
    private boolean leftIsThread;
    /**右指針**/
    private TreeNode right;
    /** 右孩子是否為線索**/
    private boolean rightIsThread;

    /**根據(jù)數(shù)據(jù)域來確定所在的指針對應位置**/
    public TreeNode(int data)
    {
        this.data = data;
        this.left = null;
        this.leftIsThread = false;
        this.right = null;
        this.rightIsThread = false;
    }

    public int getData()
    {
        return data;
    }

    public void setData(int data)
    {
        this.data = data;
    }

    public TreeNode getLeft()
    {
        return left;
    }

    public void setLeft(TreeNode left)
    {
        this.left = left;
    }

    public boolean isLeftIsThread()
    {
        return leftIsThread;
    }

    public void setLeftIsThread(boolean leftIsThread)
    {
        this.leftIsThread = leftIsThread;
    }

    public TreeNode getRight()
    {
        return right;
    }

    public void setRight(TreeNode right)
    {
        this.right = right;
    }

    public boolean isRightIsThread()
    {
        return rightIsThread;
    }

    public void setRightIsThread(boolean rightIsThread)
    {
        this.rightIsThread = rightIsThread;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (obj instanceof TreeNode )
        {
            TreeNode temp = (TreeNode) obj;
            if (temp.getData() == this.data)
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public int hashCode()
    {
        return super.hashCode() + this.data;
    }
}

二叉樹類

package com.testtree;
/*author:pier
2021/10/12
*/

public class BiTree {
    /** 根節(jié)點 **/
    private TreeNode root;
    /** 大小 **/
    private int size;
    /** 線索化的時候保存前驅(qū) **/
    private TreeNode pre = null;

    public BiTree()
    {
        this.root = null;
        this.size = 0;
        this.pre = null;
    }

    public BiTree(int[] data)
    {
        this.pre = null;
        this.size = data.length;
        // 創(chuàng)建二叉樹
        this.root = createTree(data, 1);
    }

    /**
     * 創(chuàng)建二叉樹
     *
     */
    public TreeNode createTree(int[] data, int index)
    {
        if (index > data.length)
        {
            return null;
        }
        TreeNode node = new TreeNode(data[index - 1]);
        TreeNode left = createTree(data, 2 * index);
        TreeNode right = createTree(data, 2 * index + 1);
        node.setLeft(left);
        node.setRight(right);
        return node;
    }
    /**中序遍歷**/
    public void inList(TreeNode root)
    {
        if (root != null)
        {
            inList(root.getLeft());
            System.out.print(root.getData() + ",");
            inList(root.getRight());
        }
    }

    public TreeNode getRoot()
    {
        return root;
    }

    public void setRoot(TreeNode root)
    {
        this.root = root;
    }

    public int getSize()
    {
        return size;
    }

    public void setSize(int size)
    {
        this.size = size;
    }
    /**線索化二叉樹**/
    public void inThread(TreeNode root) {
        if ( root != null ) {
            // 線索化左孩子
            inThread(root.getLeft());
            // 左孩子為空
            if ( null == root.getLeft() )
            {
                // 將左孩子設置為線索
                root.setLeftIsThread(true);
                root.setLeft(pre);
            }
            // 右孩子為空
            if ( pre != null && null == pre.getRight() )
            {
                pre.setRightIsThread(true);
                pre.setRight(root);
            }
            pre = root;
            // 線索化右孩子
            inThread(root.getRight());
        }
    }
    /**
     * 中序遍歷線索二叉樹
     *
     */
    public void inThreadList(TreeNode root)
    {
        if (root != null)
        {
            // 如果左孩子不是線索
            while (root != null && !root.isLeftIsThread())
            {
                root = root.getLeft();
            }

            do
            {
                // 如果右孩子是線索
                System.out.print(root.getData() + ",");
                if (root.isRightIsThread())
                {
                    root = root.getRight();
                }
                // 有右孩子
                else
                {
                    root = root.getRight();
                    while (root != null && !root.isLeftIsThread())
                    {
                        root = root.getLeft();
                    }
                }
            } while (root != null);
        }
    }
}

測試類

package com.testtree;

/**
 * @author pier
 */
public class Test {
    public static void main(String[] args) {
    //不要問我為什么設置這么大,結(jié)尾看我效果截圖
        int[] arr = new int[10000];
        for (int i = 0; i < arr.length; i++) {
            arr[i]=i+1;
        }
        //創(chuàng)建一顆二叉樹
        BiTree biTree = new BiTree(arr);
        //中序遍歷二叉樹
        System.out.println("中序遍歷結(jié)果如下:");
        long start1 = System.currentTimeMillis();
        biTree.inList(biTree.getRoot());
        long end1 = System.currentTimeMillis();
        System.out.println();
        System.out.println("普通遍歷時間為:"+(end1-start1)+"毫秒");
        System.out.println("\n");
        //中序遍歷將二叉樹線索化
        biTree.inThread(biTree.getRoot());
        System.out.println("線索二叉樹中序遍歷如下:");
        long start2 = System.currentTimeMillis();
        biTree.inThreadList(biTree.getRoot());
        long end2 = System.currentTimeMillis();
        System.out.println();
        System.out.println("線索二叉樹的遍歷時間為:"+(end2-start2)+"毫秒");

    }
}

運行結(jié)果

結(jié)果


當我使用1-10的時候效果截圖

截圖

完全看不出來差距,所以,哈哈才設置那么大,能夠?qū)嵺`出來線索二叉樹的遍歷速度確實更快的。

Ps:看完這篇文章,你不來點個贊嗎?不來個三連嗎?重點是,你今天Get到了嗎?別之后ALT+Insert自動生成get喲,用你那看起來不聰明的小腦袋瓜想一想。

到此這篇關于Java數(shù)據(jù)結(jié)構(gòu)二叉樹難點解析的文章就介紹到這了,更多相關Java 二叉樹內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java基礎入門 Swing中間容器的使用

    Java基礎入門 Swing中間容器的使用

    這篇文章主要介紹了Java基礎入門 Swing中間容器的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java不帶break將導致case穿透問題

    Java不帶break將導致case穿透問題

    這篇文章主要介紹了Java不帶break將導致case穿透問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Java中EnumMap和EnumSet枚舉操作類的簡單使用詳解

    Java中EnumMap和EnumSet枚舉操作類的簡單使用詳解

    這篇文章主要介紹了Java中EnumMap和EnumSet枚舉操作類的簡單使用詳解,EnumMap是Map接口的一種實現(xiàn),專門用于枚舉類型的鍵,所有枚舉的鍵必須來自同一個枚舉?EnumMap不允許鍵為空,允許值為空,需要的朋友可以參考下
    2023-11-11
  • 關于Java雙大括號{{}}的具體使用

    關于Java雙大括號{{}}的具體使用

    本文主要介紹了關于Java雙大括號{{}}的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • Java實現(xiàn)RedisUtils操作五大集合(增刪改查)

    Java實現(xiàn)RedisUtils操作五大集合(增刪改查)

    本文主要介紹了Java實現(xiàn)RedisUtils操作五大集合,文中通過示例代碼介紹的非常詳細,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • Hibernate中獲取Session的兩種方式代碼示例

    Hibernate中獲取Session的兩種方式代碼示例

    這篇文章主要介紹了Hibernate中獲取Session的兩種方式代碼示例,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Springboot中使用lombok的@Data注解方式

    Springboot中使用lombok的@Data注解方式

    這篇文章主要介紹了Springboot中使用lombok的@Data注解方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot之bootstrap和application的區(qū)別解讀

    SpringBoot之bootstrap和application的區(qū)別解讀

    這篇文章主要介紹了SpringBoot之bootstrap和application的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 詳解Java Streams 中的異常處理

    詳解Java Streams 中的異常處理

    這篇文章主要介紹了Java Streams 中的異常處理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • Java中的System.getenv()和System.getProperty()使用詳解

    Java中的System.getenv()和System.getProperty()使用詳解

    文章介紹了Java中用于讀取環(huán)境配置信息的兩種方法:System.getenv()和System.getProperty(),前者讀取系統(tǒng)環(huán)境變量,返回一個不可修改的Map;后者獲取JVM環(huán)境變量值,可以通過-D參數(shù)設置,文章還提到,通過這兩種方法可以簡化配置,不需要修改代碼
    2024-11-11

最新評論

乌苏市| 广平县| 巴林右旗| 东光县| 肃南| 乌兰县| 铁岭县| 阳原县| 榆树市| 大渡口区| 望奎县| 海南省| 九龙城区| 拉萨市| 昌平区| 咸丰县| 启东市| 厦门市| 宁安市| 宾阳县| 栾城县| 天峻县| 苗栗县| 哈尔滨市| 新郑市| 清镇市| 广州市| 海盐县| 合作市| 花莲市| 云林县| 潼南县| 萝北县| 安徽省| 板桥市| 绥化市| 左贡县| 晋中市| 东兰县| 梁山县| 涿州市|