二叉树的Java实现及特点总结

简介:

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992

    二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加。但是他也有自己的缺点:删除操作复杂。

    

    我们先介绍一些关于二叉树的概念名词。

    二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树、二叉排序树、二叉搜索树。

    完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。

    满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。

    深度——二叉树的层数,就是深度。

    

    二叉树的特点总结:

(1)树执行查找、删除、插入的时间复杂度都是O(logN)

(2)遍历二叉树的方法包括前序、中序、后序

(3)非平衡树指的是根的左右两边的子节点的数量不一致

(4) 在非空二叉树中,第i层的结点总数不超过 , i>=1;
(5)深度为h的二叉树最多有个结点(h>=1),最少有h个结点;
(6)对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;


    二叉树的Java代码实现

    首先是树的节点的定义,下面的代码中使用的是最简单的int基本数据类型作为节点的数据,如果要使用节点带有更加复杂的数据类型,换成对应的对象即可。

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  *  
  3.  * @ClassName: com.tree.TreeNode 
  4.  * @Description: 节点 
  5.  * @author zhaokaiqiang 
  6.  * @date 2014-12-5 下午4:43:24 
  7.  *  
  8.  */  
  9. public class TreeNode {  
  10.   
  11.     // 左节点  
  12.     private TreeNode lefTreeNode;  
  13.     // 右节点  
  14.     private TreeNode rightNode;  
  15.     // 数据  
  16.     private int value;  
  17.   
  18.     private boolean isDelete;  
  19.   
  20.     public TreeNode getLefTreeNode() {  
  21.         return lefTreeNode;  
  22.     }  
  23.   
  24.     public void setLefTreeNode(TreeNode lefTreeNode) {  
  25.         this.lefTreeNode = lefTreeNode;  
  26.     }  
  27.   
  28.     public TreeNode getRightNode() {  
  29.         return rightNode;  
  30.     }  
  31.   
  32.     public void setRightNode(TreeNode rightNode) {  
  33.         this.rightNode = rightNode;  
  34.     }  
  35.   
  36.     public int getValue() {  
  37.         return value;  
  38.     }  
  39.   
  40.     public void setValue(int value) {  
  41.         this.value = value;  
  42.     }  
  43.   
  44.     public boolean isDelete() {  
  45.         return isDelete;  
  46.     }  
  47.   
  48.     public void setDelete(boolean isDelete) {  
  49.         this.isDelete = isDelete;  
  50.     }  
  51.   
  52.     public TreeNode() {  
  53.         super();  
  54.     }  
  55.   
  56.     public TreeNode(int value) {  
  57.         this(nullnull, value, false);  
  58.     }  
  59.   
  60.     public TreeNode(TreeNode lefTreeNode, TreeNode rightNode, int value,  
  61.             boolean isDelete) {  
  62.         super();  
  63.         this.lefTreeNode = lefTreeNode;  
  64.         this.rightNode = rightNode;  
  65.         this.value = value;  
  66.         this.isDelete = isDelete;  
  67.     }  
  68.   
  69.     @Override  
  70.     public String toString() {  
  71.         return "TreeNode [lefTreeNode=" + lefTreeNode + ", rightNode="  
  72.                 + rightNode + ", value=" + value + ", isDelete=" + isDelete  
  73.                 + "]";  
  74.     }  
  75.   
  76. }  

    下面给出二叉树的代码实现。由于在二叉树中进行节点的删除非常繁琐,因此,下面的代码使用的是利用节点的isDelete字段对节点的状态进行标识

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  *  
  3.  * @ClassName: com.tree.Tree 
  4.  * @Description: 二叉树的定义 
  5.  * @author zhaokaiqiang 
  6.  * @date 2014-12-8 上午7:51:49 
  7.  *  
  8.  */  
  9.   
  10. public class BinaryTree {  
  11.   
  12.     // 根节点  
  13.     private TreeNode root;  
  14.   
  15.     public TreeNode getRoot() {  
  16.         return root;  
  17.     }  
  18.   
  19.     /** 
  20.      * 插入操作 
  21.      *  
  22.      * @param value 
  23.      */  
  24.     public void insert(int value) {  
  25.   
  26.         TreeNode newNode = new TreeNode(value);  
  27.   
  28.         if (root == null) {  
  29.             root = newNode;  
  30.             root.setLefTreeNode(null);  
  31.             root.setRightNode(null);  
  32.         } else {  
  33.   
  34.             TreeNode currentNode = root;  
  35.             TreeNode parentNode;  
  36.   
  37.             while (true) {  
  38.   
  39.                 parentNode = currentNode;  
  40.                 // 往右放  
  41.                 if (newNode.getValue() > currentNode.getValue()) {  
  42.                     currentNode = currentNode.getRightNode();  
  43.                     if (currentNode == null) {  
  44.                         parentNode.setRightNode(newNode);  
  45.                         return;  
  46.                     }  
  47.                 } else {  
  48.                     // 往左放  
  49.                     currentNode = currentNode.getLefTreeNode();  
  50.                     if (currentNode == null) {  
  51.                         parentNode.setLefTreeNode(newNode);  
  52.                         return;  
  53.                     }  
  54.   
  55.                 }  
  56.             }  
  57.         }  
  58.     }  
  59.   
  60.     /** 
  61.      * 查找 
  62.      *  
  63.      * @param key 
  64.      * @return 
  65.      */  
  66.     public TreeNode find(int key) {  
  67.   
  68.         TreeNode currentNode = root;  
  69.   
  70.         if (currentNode != null) {  
  71.   
  72.             while (currentNode.getValue() != key) {  
  73.   
  74.                 if (currentNode.getValue() > key) {  
  75.                     currentNode = currentNode.getLefTreeNode();  
  76.                 } else {  
  77.                     currentNode = currentNode.getRightNode();  
  78.                 }  
  79.   
  80.                 if (currentNode == null) {  
  81.                     return null;  
  82.                 }  
  83.   
  84.             }  
  85.   
  86.             if (currentNode.isDelete()) {  
  87.                 return null;  
  88.             } else {  
  89.                 return currentNode;  
  90.             }  
  91.   
  92.         } else {  
  93.             return null;  
  94.         }  
  95.   
  96.     }  
  97.   
  98.     /** 
  99.      * 中序遍历 
  100.      *  
  101.      * @param treeNode 
  102.      */  
  103.     public void inOrder(TreeNode treeNode) {  
  104.         if (treeNode != null && treeNode.isDelete() == false) {  
  105.             inOrder(treeNode.getLefTreeNode());  
  106.             System.out.println("--" + treeNode.getValue());  
  107.             inOrder(treeNode.getRightNode());  
  108.         }  
  109.     }  
  110.   
  111. }  

    在上面对二叉树的遍历操作中,使用的是中序遍历,这样遍历出来的数据是增序的。

    下面是测试代码:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class Main {  
  2.   
  3.     public static void main(String[] args) {  
  4.   
  5.         BinaryTree tree = new BinaryTree();  
  6.         // 添加数据测试  
  7.         tree.insert(10);  
  8.         tree.insert(40);  
  9.         tree.insert(20);  
  10.         tree.insert(3);  
  11.         tree.insert(49);  
  12.         tree.insert(13);  
  13.         tree.insert(123);  
  14.   
  15.         System.out.println("root=" + tree.getRoot().getValue());  
  16.         // 排序测试  
  17.         tree.inOrder(tree.getRoot());  
  18.         // 查找测试  
  19.         if (tree.find(10) != null) {  
  20.             System.out.println("找到了");  
  21.         } else {  
  22.             System.out.println("没找到");  
  23.         }  
  24.         // 删除测试  
  25.         tree.find(40).setDelete(true);  
  26.   
  27.         if (tree.find(40) != null) {  
  28.             System.out.println("找到了");  
  29.         } else {  
  30.             System.out.println("没找到");  
  31.         }  
  32.   
  33.     }  
  34.   
  35. }  
相关文章
|
2月前
|
算法 Java
算法:Java计算二叉树从根节点到叶子结点的最大路径和
算法:Java计算二叉树从根节点到叶子结点的最大路径和
|
2月前
|
Java
Java二叉树超详解(常用方法介绍)(2)
Java二叉树超详解(常用方法介绍)(2)
|
2月前
|
存储 Java
JAVA 二叉树超详解(1)
JAVA 二叉树超详解(1)
|
5月前
|
Java
2415. 反转二叉树的奇数层 --力扣 --JAVA
给你一棵 完美 二叉树的根节点 root ,请你反转这棵树中每个 奇数 层的节点值。 例如,假设第 3 层的节点值是 [2,1,3,4,7,11,29,18] ,那么反转后它应该变成 [18,29,11,7,4,3,1,2] 。 反转后,返回树的根节点。 完美 二叉树需满足:二叉树的所有父节点都有两个子节点,且所有叶子节点都在同一层。 节点的 层数 等于该节点到根节点之间的边数。
28 0
|
5月前
|
Java
145. 二叉树的后序遍历 --力扣 --JAVA
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
20 0
|
5月前
|
Java
199. 二叉树的右视图 --力扣 --JAVA
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
29 0
|
5月前
|
Java
124. 二叉树中的最大路径和 --力扣 --JAVA
二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root ,返回其 最大路径和 。
26 1
|
4月前
|
Java Go C++
Golang每日一练(leetDay0085) 2的幂、数字 1 的个数
Golang每日一练(leetDay0085) 2的幂、数字 1 的个数
24 0
Golang每日一练(leetDay0085) 2的幂、数字 1 的个数
|
4月前
|
Java C++ Python
Rust每日一练(Leetday0013) 解数独、外观数列、组合总和
Rust每日一练(Leetday0013) 解数独、外观数列、组合总和
36 0
Rust每日一练(Leetday0013) 解数独、外观数列、组合总和
|
4月前
|
算法 Python Java
Java每日一练(20230429) 二叉树后序遍历、删除无效括号、合并有序链表
Java每日一练(20230429) 二叉树后序遍历、删除无效括号、合并有序链表
29 0
Java每日一练(20230429) 二叉树后序遍历、删除无效括号、合并有序链表