二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加。但是他也有自己的缺点:删除操作复杂。
我们先介绍一些关于二叉树的概念名词。
二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树、二叉排序树、二叉搜索树。
完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
深度——二叉树的层数,就是深度。
二叉树的Java代码实现
树的节点的定义,我在代码中使用的是最简单的int基本数据类型作为节点的数据:
节点定义类:
public class TreeNode {
private TreeNode leftTreeNode;
private TreeNode rightTreeNode;
private int value;
private boolean isDelete;
public TreeNode() {
super();
}
public TreeNode(int value){
this(null,null,value,false);
}
public TreeNode(TreeNode leftTreeNode, TreeNode rightTreeNode, int value,
boolean isDelete) {
super();
this.leftTreeNode = leftTreeNode;
this.rightTreeNode = rightTreeNode;
this.value = value;
this.isDelete = isDelete;
}
public TreeNode getLeftTreeNode() {
return leftTreeNode;
}
public void setLeftTreeNode(TreeNode leftTreeNode) {
this.leftTreeNode = leftTreeNode;
}
public TreeNode getRightTreeNode() {
return rightTreeNode;
}
public void setRightTreeNode(TreeNode rightTreeNode) {
this.rightTreeNode = rightTreeNode;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isDelete() {
return isDelete;
}
public void setDelete(boolean isDelete) {
this.isDelete = isDelete;
}
@Override
public String toString() {
return "TreeNode [lefTreeNode=" + leftTreeNode + ", rightNode="
+ rightTreeNode + ", value=" + value + ", isDelete=" + isDelete
+ "]";
}
}
二叉树类(包含插入,查找,前序,中序,后序的遍历):
public class BinaryTree {
/**
* 根节点
*/
private TreeNode root;
public TreeNode getRoot(){
return root;
}
/**
* 创建人:mly
* 创建时间:2019-5-16下午2:23:33
* 返回类型:
* 描述:二叉树的插入
*/
public void insert(int value){
TreeNode newNode = new TreeNode(value);
if(root==null){
root=newNode;
root.setRightTreeNode(null);
root.setLeftTreeNode(null);
}else{
TreeNode currentNode = root;
TreeNode parentNode;
while(true){
parentNode=currentNode;
//判断新插入节点的值是否大于当前节点的值,如果大于则插入到右侧,否则插入到左侧
if(newNode.getValue()>currentNode.getValue()){
currentNode=currentNode.getRightTreeNode();//如果有数,则此节点为当前节点
if(currentNode==null){
parentNode.setRightTreeNode(newNode);
return;
}
}else{
currentNode = currentNode.getLeftTreeNode();
if(currentNode==null){
parentNode.setLeftTreeNode(newNode);
return ;
}
}
}
}
}
/**
*
* 创建人:mly
* 创建时间:2019-5-16下午2:52:29
* 返回类型:
* 描述:二叉树的查找
*/
public TreeNode find(int key){
TreeNode currentNode =root;
if(currentNode!=null){
while(currentNode.getValue()!=key){
if(currentNode.getValue()>key){
currentNode=currentNode.getLeftTreeNode();
}else{
currentNode=currentNode.getRightTreeNode();
}
if(currentNode==null){
return null;
}
}
if(currentNode.isDelete()){
return null;
}else{
return currentNode;
}
}else{
return null;
}
}
/**
*
* 创建人:mly
* 创建时间:2019-5-16下午3:00:26
* 返回类型:
* 描述:中序遍历
*/
public void inOrder(TreeNode treeNode){
if(treeNode!=null&&treeNode.isDelete()==false){
inOrder(treeNode.getLeftTreeNode());
System.out.println("中序---"+treeNode.getValue());
inOrder(treeNode.getRightTreeNode());
}
}
/**
*
* 创建人:mly
* 创建时间:2019-5-16下午3:05:56
* 返回类型:
* 描述:后序遍历
*/
public void afterOrder(TreeNode treeNode){
if(treeNode!=null&&treeNode.isDelete()==false){
afterOrder(treeNode.getLeftTreeNode());
afterOrder(treeNode.getRightTreeNode());
System.out.println("后序---"+treeNode.getValue());
}
}
public void beforOrder(TreeNode treeNode){
if(treeNode!=null&&treeNode.isDelete()==false){
System.out.println("前序---"+treeNode.getValue());
beforOrder(treeNode.getLeftTreeNode());
beforOrder(treeNode.getRightTreeNode());
}
}
}
测试类代码
public class BinaryTreeTest {
public static void main(String[] args) {
BinaryTree tree = new BinaryTree();
tree.insert(23);
tree.insert(20);
tree.insert(23);
tree.insert(10);
tree.insert(13);
tree.insert(40);
tree.insert(29);
tree.insert(45);
tree.insert(2);
TreeNode root = tree.getRoot();
tree.inOrder(root);
tree.afterOrder(root);
tree.beforOrder(root);
}
}
打印的结果:
中序---2
中序---10
中序---13
中序---20
中序---23
中序---23
中序---29
中序---40
中序---45
后序---2
后序---13
后序---10
后序---23
后序---20
后序---29
后序---45
后序---40
后序---23
前序---23
前序---20
前序---10
前序---2
前序---13
前序---23
前序---40
前序---29
前序---45
对于二叉树的遍历方式一般分为三种先序、中序、后序三种方式:
先序遍历(根左右)
若二叉树为空,则不进行任何操作:否则
1、访问根结点。
2、先序方式遍历左子树。
3、先序遍历右子树。
中序遍历 (左根右)
若二叉树为空,则不进行任何操作:否则
1、中序遍历左子树。
2、访问根结点。
3、中序遍历右子树。
后序遍历 (左右根)
若二叉树为空,则不进行任何操作:否则
1、后序遍历左子树。
2、后序遍历右子树。
3、放问根结点。