二叉树
Posted hyunbar
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树相关的知识,希望对你有一定的参考价值。
一、为什么需要树这种数据结构
1、数组存储方式的分析
优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。
缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低 [示意图]
2、链式存储方式的分析
优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可, 删除效率也很好)。
缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历)
3、树存储方式的分析
能提高数据存储,读取的效率, 比如利用 二叉排序树(Binary Sort Tree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度
二、二叉树的常用术语
- 节点
- 根节点
- 父节点
- 子节点
- 叶子节点 (没有子节点的节点)
- 节点的权(节点值)
- 路径(从root节点找到该节点的路线)
- 层
- 子树
- 树的高度(最大层数)
- 森林 :多颗子树构成森林
三、二叉树的概念
- 树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树。
- 二叉树的子节点分为左节点和右节点
- 如果该二叉树的所有叶子节点都在最后一层,并且结点总数= 2^n -1 , n 为层数,则我们称为满二叉树。
- 如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。
四、遍历
1、前序遍历
1 //编写前序遍历的方法 2 public void preOrder() 3 System.out.println(this); //先输出父结点 4 //递归向左子树前序遍历 5 if(this.left != null) 6 this.left.preOrder(); 7 8 //递归向右子树前序遍历 9 if(this.right != null) 10 this.right.preOrder(); 11 12
2、中序遍历
1 //中序遍历 2 public void infixOrder() 3 4 //递归向左子树中序遍历 5 if(this.left != null) 6 this.left.infixOrder(); 7 8 //输出父结点 9 System.out.println(this); 10 //递归向右子树中序遍历 11 if(this.right != null) 12 this.right.infixOrder(); 13 14
3、后序遍历
1 //后序遍历 2 public void postOrder() 3 if(this.left != null) 4 this.left.postOrder(); 5 6 if(this.right != null) 7 this.right.postOrder(); 8 9 System.out.println(this); 10
五、完整代码
1 package com.atguigu.tree; 2 3 import org.junit.Test; 4 5 /** 6 * @author z 7 * @createdate 2019-08-15 11:14 8 */ 9 public class BinaryTreeTest 10 @Test 11 public void test() 12 BinaryTree b = new BinaryTree(); 13 HeroNode root = new HeroNode(1, "宋江"); 14 HeroNode n1 = new HeroNode(2, "吴用"); 15 HeroNode n2 = new HeroNode(3, "玉麒麟"); 16 HeroNode n3 = new HeroNode(4, "关胜"); 17 18 b.setRoot(root); 19 root.setLeft(n1); 20 root.setRight(n2); 21 n1.setLeft(n3); 22 b.proOrder(); 23 24 b.findproOrder(5); 25 26 27 28 class BinaryTree 29 public void setRoot(HeroNode root) 30 this.root = root; 31 32 33 private HeroNode root; 34 35 //前序遍历 36 public void proOrder() 37 if (this.root != null) 38 this.root.proOrder(); 39 else 40 System.out.println("二叉树为空"); 41 42 43 44 //中序遍历 45 public void infixOrder() 46 if (this.root != null) 47 this.root.infixOrder(); 48 else 49 System.out.println("二叉树为空"); 50 51 52 53 //后序遍历 54 public void postOrder() 55 if (this.root != null) 56 this.root.postOrder(); 57 else 58 System.out.println("二叉树为空"); 59 60 61 62 //前序查找 63 public void findproOrder(int no) 64 if (this.root != null) 65 HeroNode heroNode = this.root.findproOrder(no); 66 if (heroNode != null) 67 System.out.println(heroNode); 68 else 69 System.out.println("未知的英雄编号:" + no); 70 else 71 System.out.println("二叉树为空"); 72 73 74 75 //中序查找 76 public void findinfixOrder(int no) 77 if (this.root != null) 78 HeroNode heroNode = this.root.findinfixOrder(no); 79 if (heroNode != null) 80 System.out.println(heroNode); 81 else 82 System.out.println("未知的英雄编号:" + no); 83 else 84 System.out.println("二叉树为空"); 85 86 87 88 //后序查找 89 public void findpostOrder(int no) 90 if (this.root != null) 91 HeroNode heroNode = this.root.findpostOrder(no); 92 if (heroNode != null) 93 System.out.println(heroNode); 94 else 95 System.out.println("未知的英雄编号:" + no); 96 else 97 System.out.println("二叉树为空"); 98 99 100 101 102 class HeroNode 103 private int no; 104 private String name; 105 private HeroNode left; //默认null 106 private HeroNode right; //默认null 107 108 @Override 109 public String toString() 110 return "HeroNode" + 111 "no=" + no + 112 ", name=‘" + name + ‘\\‘‘ + 113 /*", left=" + left + 114 ", right=" + right +*/ 115 ‘‘; 116 117 118 public HeroNode(int no, String name) 119 this.no = no; 120 this.name = name; 121 122 123 public int getNo() 124 return no; 125 126 127 public void setNo(int no) 128 this.no = no; 129 130 131 public String getName() 132 return name; 133 134 135 public void setName(String name) 136 this.name = name; 137 138 139 public HeroNode getLeft() 140 return left; 141 142 143 public void setLeft(HeroNode left) 144 this.left = left; 145 146 147 public HeroNode getRight() 148 return right; 149 150 151 public void setRight(HeroNode right) 152 this.right = right; 153 154 155 //编写前序遍历的方法 156 public void proOrder() 157 System.out.println(this); 158 if (this.left != null) 159 this.left.proOrder(); 160 161 if (this.right != null) 162 this.right.proOrder(); 163 164 165 166 //编写中序遍历的方法 167 public void infixOrder() 168 if (this.left != null) 169 this.left.infixOrder(); 170 171 System.out.println(this); 172 if (this.right != null) 173 this.right.infixOrder(); 174 175 176 177 //编写后序遍历的方法 178 public void postOrder() 179 if (this.left != null) 180 this.left.postOrder(); 181 182 if (this.right != null) 183 this.right.postOrder(); 184 185 System.out.println(this); 186 187 188 //编写前序查找的方法 189 public HeroNode findproOrder(int no) 190 if (this.no == no) 191 return this; 192 193 //1.则判断当前结点的左子节点是否为空,如果不为空,则递归前序查找 194 //2.如果左递归前序查找,找到结点,则返回 195 HeroNode h = null; 196 if (this.left != null) 197 h = this.left.findproOrder(no); 198 199 if (h != null) 200 return h; 201 202 //1.左递归前序查找,找到结点,则返回,否继续判断, 203 //2.当前的结点的右子节点是否为空,如果不空,则继续向右递归前序查找 204 if (this.right != null) 205 h = this.right.findproOrder(no); 206 207 return h; 208 209 210 //编写中序查找的方法 211 public HeroNode findinfixOrder(int no) 212 HeroNode h = null; 213 if (this.left != null) 214 h = this.left.findinfixOrder(no); 215 216 if (h != null) 217 return h; 218 219 if (this.no == no) 220 return this; 221 222 if (this.right != null) 223 h = this.right.findinfixOrder(no); 224 225 return h; 226 227 228 //编写后序查找的方法 229 public HeroNode findpostOrder(int no) 230 HeroNode h = null; 231 if (this.left != null) 232 h = this.left.findpostOrder(no); 233 234 if (h != null) 235 return h; 236 237 if (this.right != null) 238 h = this.right.findpostOrder(no); 239 240 if (h != null) 241 return h; 242 243 if (this.no == no) 244 return this; 245 246 return null; 247 248
以上是关于二叉树的主要内容,如果未能解决你的问题,请参考以下文章