一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Java數(shù)據(jù)結(jié)構(gòu)二叉樹難點(diǎn)解析

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

2022-02-28 00:48pier~呀 Java教程

樹是一種重要的非線性數(shù)據(jù)結(jié)構(gòu),直觀地看,它是數(shù)據(jù)元素(在樹中稱為結(jié)點(diǎn))按分支關(guān)系組織起來的結(jié)構(gòu),很象自然界中的樹那樣。樹結(jié)構(gòu)在客觀世界中廣泛存在,如人類社會的族譜和各種社會組織機(jī)構(gòu)都可用樹形象表示

前言

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

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

 什么是線索二叉樹

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

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

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

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

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

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

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

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

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

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

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

怎么去把二叉樹線索化

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

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

本博文主要討論的是中序遍歷
它的中序遍歷結(jié)果就是abcde f ghi

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

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

先畫線索二叉樹

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

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

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

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

即形成了一個(gè)特殊的雙向鏈表,之所以特殊,以f–>e為例,f–>e并不是直接到達(dá),而是通過f–>b–>d–>e間接到達(dá)。

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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ù)域來確定所在的指針對應(yīng)位置**/
    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;
    }
}

二叉樹類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.testtree;
/*author:pier
2021/10/12
*/
 
public class bitree {
    /** 根節(jié)點(diǎn) **/
    private treenode root;
    /** 大小 **/
    private int size;
    /** 線索化的時(shí)候保存前驅(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() )
            {
                // 將左孩子設(shè)置為線索
                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);
        }
    }
}

測試類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.testtree;
 
/**
 * @author pier
 */
public class test {
    public static void main(string[] args) {
    //不要問我為什么設(shè)置這么大,結(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("普通遍歷時(shí)間為:"+(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("線索二叉樹的遍歷時(shí)間為:"+(end2-start2)+"毫秒");
 
    }
}

運(yùn)行結(jié)果

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


當(dāng)我使用1-10的時(shí)候效果截圖

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

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

ps:看完這篇文章,你不來點(diǎn)個(gè)贊嗎?不來個(gè)三連嗎?重點(diǎn)是,你今天get到了嗎?別之后alt+insert自動生成get喲,用你那看起來不聰明的小腦袋瓜想一想。

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

原文鏈接:https://blog.csdn.net/qq_43325476/article/details/120716127

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产美女极品免费视频 | 天天干天天操天天爽 | 爽好舒服使劲添高h视频 | ass日本乱妇ass | 成人性生交小说免费看 | 大伊香蕉在线精品不卡视频 | 射逼网| 经典三级四虎在线观看 | 男男羞羞视频网站国产 | 国产3p在线| 天堂va亚洲va欧美va国产 | 日本红怡院亚洲红怡院最新 | 亚洲成人mv | 青青草原手机在线视频 | 国产日本久久久久久久久婷婷 | 欧美性色黄大片四虎影视 | xxxx成人| 精品国产成人高清在线 | 国产精品久久久久久久久久久久久久 | 午夜精品久久久久久久99蜜桃i | 欧美亚洲国产另类 | 久久精品视在线观看85 | 亚洲精品国产在线网站 | 国产成+人+综合+亚洲欧美丁香花 | 美人的淫事[纯hh] | 欧美性xxxxxx爱 | 99精品国产高清自在线看超 | 性xxxx18学生第一次出血 | 毛片亚洲毛片亚洲毛片 | 亚洲精品在线网址 | 色中文网 | 女仆色永久免费网站 | 日韩在线视频在线 | 古装床戏做爰无遮挡三级 | 精品在线免费观看 | 日本成人黄色网址 | 嫩草影院国产 | 日b视频免费 | 国产一二在线观看视频网站 | 国产精品一区三区 | 美女用手扒开粉嫩的屁股 |