数据结构与算法 树结构 二叉树

枫叶

树结构

树结构概述

啥是树结构

树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样

为什么使用树结构

因为线性结构插入和查找不方便、效率不是太高

树的基本概念

  • 根节点

根节点就是最开始的那一个节点、就是祖宗

  • 双亲节点

双亲节点就是一个节点下面有两个节点、就是他自己即是爹又是娘、自己就能生两个节点出来

  • 子节点

子节点就是被生出来的那个

  • 路径

路径就是从一个节点到另一个节点所经过的地方、走的路

  • 节点的度

节点的度就是一个节点有几个子节点、有几个子节点那么他的度就是多少

  • 节点的权

节点的权就是当前节点里面存的内容、存的内容是多少它的权就是多少

  • 叶子节点

叶子节点就是当前节点没有子节点、他就是最后一个了

  • 子树

子树就是当前这个树里面的叉、把里面的几个节点也看成一个树、那么这个树就是它的子树

层就是每个节点的层次、就是例如辈分一样、太爷、爷爷、爹、儿子、孙子、重孙子

  • 树的高度

树的高度就是最大的层数

  • 森林

森林就是将多个树连在一起组成一个森林

树结构

二叉树

啥是二叉树

二叉树就是任何一个节点的子节点数量不超过2

二叉树的子节点分为左节点和右节点、并且左右节点不可颠倒位置

二叉树

满二叉树

除最后一层无任何子节点外、每一层上的所有结点都有两个子结点的二叉树

一个二叉树、如果每一个层的结点数都达到最大值、则这个二叉树就是满二叉树。也就是说、如果一个二叉树的层数为K、且结点总数是(2^k) -1 则它就是满二叉树

完全二叉树

所有叶子节点都在最后一层或倒数第二层、且最后一层的叶子节点在左边连续、倒数第二层叶子节点在右边连续

一棵深度为k的有n个结点的二叉树、对树中的结点按从上至下、从左到右的顺序进行编号、如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同、则这棵二叉树称为完全二叉树

链式存储的二叉树

CRUD

  • TreeNode(节点)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
public class TreeNode {

//定义当前节点
private Integer value;

//定义左节点
private TreeNode leftNode;

//定义右节点
private TreeNode rightNode;

//初始化节点
public TreeNode(Integer value){
this.value = value;
}

public Integer getValue() {
return value;
}

public void setValue(Integer value) {
this.value = value;
}

//为左节点定义
public void setLeftNode(TreeNode leftNode) {
this.leftNode = leftNode;
}

//取出左节点
public TreeNode getLeftNode() {
return leftNode;
}

//为右节点定义
public void setRightNode(TreeNode rightNode) {
this.rightNode = rightNode;
}

//取出右节点
public TreeNode getRightNode() {
return rightNode;
}

/**
* 前序遍历
* node 当前节点
*/
public void frontShow(TreeNode node){

//显示当前节点
System.out.print(value + "\t");

//判断左节点是否为空
if(null != leftNode){
//递归
leftNode.frontShow(node.getLeftNode());
}
//判断右节点是否为空
if(null != rightNode){
//递归
rightNode.frontShow(node.getRightNode());
}
}

/**
* 中序遍历
* @param node
*/
public void middleShow(TreeNode node){

if(null != leftNode){
leftNode.middleShow(node.getLeftNode());
}

System.out.print(value + "\t");

if(null != rightNode){
rightNode.middleShow(node.getRightNode());
}
}

/**
* 后序遍历
* @param node
*/
public void rearShow(TreeNode node){


if(null != leftNode){
leftNode.rearShow(node.getLeftNode());
}

if(null != rightNode){
rightNode.rearShow(node.getRightNode());
}
System.out.print(value + "\t");
}

/**
* 前序查找
* @param i
* @return
*/
public TreeNode frontSearch(int i){

//定义用于存放查到的数据变量
TreeNode target = null;

//判断当前权是否为要查找的数据
if(i == value){
return this;
}
//判断左节点
if(null != leftNode){
//递归
target = leftNode.frontSearch(i);
}
//判断是否找到要查找的数据
if(null != target){
return target;
}
//判断右节点
if(null != rightNode){
target = rightNode.frontSearch(i);
}
return target;
}

/**
* 删除
* @param i
*/
public void delete(int i){

//定义变量存放当前节点
TreeNode node = this;

//判断当前节点的左节点是否是要删除的
if(null != leftNode && node.leftNode.value == i ){
node.rightNode = null;
return ;
}
//判断当前节点的右节点是否是要删除的
if (null != rightNode && node.rightNode.value == i){
node.rightNode = null;
return ;
}

//如果当前节点的左节点没有找到则继续向下找、将左节点作为当前节点、开始递归
node = leftNode;
if(node != null){
node.delete(i);
}
//如果当前节点的右节点没有找到则继续向下找、将右节点作为当前节点、开始递归
node = rightNode;
if(node != null){
node.delete(i);
}
}
}
  • BinaryTree(树)
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
public class BinaryTree {

//定义一个根节点
private TreeNode treeNode;

//获取根节点
public TreeNode getTreeNode() {
return treeNode;
}

//设置根节点
public void setTreeNode(TreeNode treeNode) {
this.treeNode = treeNode;
}

/**
* 前序遍历
* node 当前节点
*/
public void frontShow(TreeNode node){
if(null != treeNode){
treeNode.frontShow(node);
}
}

/**
* 中序遍历
* @param node
*/
public void middleShow(TreeNode node){
if(null != treeNode){
treeNode.middleShow(node);
}
}

/**
* 后序遍历
* @param node
*/
public void rearShow(TreeNode node){
if(null != treeNode){
treeNode.rearShow(node);
}
}

/**
* 前置查找
* @param i
* @return
*/
public TreeNode frontSearch(int i){

return treeNode.frontSearch(i);
}

/**
* 删除子树
* @param i
*/
public void delete(int i){
//判断删除的是否为树的根节点
if(treeNode.getValue() == i){
treeNode = null;
}else{
treeNode.delete(i);
}
}
}
  • main
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
public class TestBinaryTree {

public static void main(String[] args) {

//创建一个树的实例化对象
BinaryTree tree = new BinaryTree();

//创建一个节点的实例化对象
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(5);
TreeNode node6 = new TreeNode(6);
TreeNode node7 = new TreeNode(7);


//为树添加根节点
tree.setTreeNode(node1);
//为根节点添加左节点
node1.setLeftNode(node2);
//为根节点添加右节点
node1.setRightNode(node3);

//为第二层节点添加左右节点
node2.setLeftNode(node4);
node2.setRightNode(node5);
node3.setLeftNode(node6);
node3.setRightNode(node7);



//前序遍历
tree.frontShow(node1);
System.out.println();
//中序遍历
tree.middleShow(node1);

System.out.println();
//后序遍历
tree.rearShow(node1);

System.out.println();
//前序查找
System.out.println(tree.frontSearch(6));

//删除
tree.delete(1);
//前序遍历
tree.frontShow(node1);
}
}

顺序存储的二叉树

通常情况下只考虑满二叉树和完全二叉树、因为普通的二叉树没有意义

顺序存储二叉树

  • 第n个元素的左子节点

2 * n + 1

  • 第n个元素的右子节点

2 * n + 2

  • 第n个元素的父节点

(n - 1) / 2

顺序存储的二叉树遍历

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
public class ArrayBinaryTree {

//定义数组
private int[] data;

//初始化
public ArrayBinaryTree(int[] data){
this.data = data;
}

//从哪里开始
public void frontShow(){
frontShow(0);
}

//前序遍历
public void frontShow(int index){

//显示数据
System.out.println(data[index]);

//判断是否有数据
if(data == null || data.length == 0){
return ;
}
//判断左节点是否在数组里面
if(2 * index + 1 < data.length){
//遍历
frontShow(2 * index + 1);
}
//判断右节点是否在数组里面
if(2 * index + 2 < data.length){
//遍历
frontShow(2 * index + 2);
}
}
}
1
2
3
4
5
6
7
8
9
public class Test {

public static void main(String[] args) {
int[] data = new int[]{1,2,3,4,5,6,7};
ArrayBinaryTree arrayBinaryTree = new ArrayBinaryTree(data);

arrayBinaryTree.frontShow();
}
}

正确的开始、微小的长进、然后持续、嘿、我是小博、带你一起看我目之所及的世界……

-------------本文结束 感谢您的阅读-------------

本文标题:数据结构与算法 树结构 二叉树

文章作者:小博

发布时间:2021年08月10日 - 19:41

最后更新:2021年08月10日 - 19:43

原始链接:https://codexiaobo.github.io/posts/3265814123/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。