二叉树

一、为什么需要树这种数据结构

  1、数组存储方式的分析
  优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。
  缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低 [示意图]
  2、链式存储方式的分析
  优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可, 删除效率也很好)。
  缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历)
  3、树存储方式的分析
  能提高数据存储,读取的效率,  比如利用 二叉排序树(Binary Sort Tree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度

二、二叉树的常用术语

  1. 节点
  2. 根节点
  3. 父节点
  4. 子节点
  5. 叶子节点 (没有子节点的节点)
  6. 节点的权(节点值)
  7. 路径(从root节点找到该节点的路线)
  8. 子树
  9. 树的高度(最大层数)
  10. 森林 :多颗子树构成森林

三、二叉树的概念 

  1. 树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树。
  2. 二叉树的子节点分为左节点和右节点
  3. 如果该二叉树的所有叶子节点都在最后一层,并且结点总数= 2^n -1 , n 为层数,则我们称为满二叉树。
  4. 如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。

    

 

   

 

   

四、遍历

  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   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 }

 

posted @ 2019-09-10 12:28  hyunbar  阅读(206)  评论(0编辑  收藏  举报