所谓非线性结构,是指在该类结构中至少存在一个数据元素,它具有两个或者两个以上的直接前驱或直接后驱。树型结构就是一种非常重要且应用广泛的非线性结构。

树有可以分为二叉树和非二叉树,其中二叉树使用最为广泛。二叉树就是每个节点最多有两个子树的有序树,通常子树的根被称作“左子树”和“右子树”。
如果我们给二叉树加一个额外的条件,就可以得到一种被称作二叉搜索树(binary search tree)的特殊二叉树。二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
下面就是一个搜索二叉树:

二叉树的遍历是根据一种特定的顺序访问树的每一个节点。比较常用的有前序遍历,中序遍历和后序遍历。而二叉搜索树最常用的是中序遍历。因为中序遍历后可以得到一个排序的元素集合。

二叉树也有两种实现方式,一种是基于数组的二叉树,另一种是基于链表的二叉树,但是基于数组的二叉树可能会产生一定的空间浪费,当二叉树为完全二叉树时,则不会存在浪费空间的问题了。而链式存储无论二叉树结构如何都不会存在这样的问题,所以本节案例的实现也采用基于链表的方式实现。
下面给出完整的自定二叉树的实现类,以及二叉树常见的操作方法。
项目结构图如下:

Node.java
public class Node {
int data; //节点数据
Node leftChild; //左子节点的引用
Node rightChild; //右子节点的引用
boolean isDelete;//表示节点是否被删除
public Node(int data){
this.data = data;
}
//打印节点内容
public void display(){
System.out.println(data);
}
}
Tree.java
package com.simoniu.binarytree;
public interface Tree {
//查找节点
public Node find(int key);
//插入新节点
public boolean insert(int data);
//中序遍历
public void infixOrder(Node current);
//前序遍历
public void preOrder(Node current);
//后序遍历
public void postOrder(Node current);
//查找最大值
public Node findMax();
//查找最小值
public Node findMin();
//删除节点
public boolean delete(int key);
}
BinaryTree.java
public class BinaryTree implements Tree {
//表示根节点
private Node root;
//查找节点
public Node find(int key) {
Node current = root;
while (current != null) {
if (current.data > key) {//当前值比查找值大,搜索左子树
current = current.leftChild;
} else if (current.data < key) {//当前值比查找值小,搜索右子树
current = current.rightChild;
} else {
return current;
}
}
return null;//遍历完整个树没找到,返回null
}
//插入节点
public boolean insert(int data) {
Node newNode = new Node(data);
if (root == null) {//当前树为空树,没有任何节点
root = newNode;
return true;
} else {
Node current = root;
Node parentNode = null;
while (current != null) {
parentNode = current;
if (current.data > data) {//当前值比插入值大,搜索左子节点
current = current.leftChild;
if (current == null) {//左子节点为空,直接将新值插入到该节点
parentNode.leftChild = newNode;
return true;
}
} else {
current = current.rightChild;
if (current == null) {//右子节点为空,直接将新值插入到该节点
parentNode.rightChild = newNode;
return true;
}
}
}
}
return false;
}
//中序遍历
public void infixOrder(Node current) {
if (current != null) {
infixOrder(current.leftChild);
System.out.print(current.data + " ");
infixOrder(current.rightChild);
}
}
//前序遍历
public void preOrder(Node current) {
if (current != null) {
System.out.print(current.data + " ");
preOrder(current.leftChild);
preOrder(current.rightChild);
}
}
//后序遍历
public void postOrder(Node current) {
if (current != null) {
postOrder(current.leftChild);
postOrder(current.rightChild);
System.out.print(current.data + " ");
}
}
//找到最大值
public Node findMax() {
Node current = root;
Node maxNode = current;
while (current != null) {
maxNode = current;
current = current.rightChild;
}
return maxNode;
}
//找到最小值
public Node findMin() {
Node current = root;
Node minNode = current;
while (current != null) {
minNode = current;
current = current.leftChild;
}
return minNode;
}
//删除节点
@Override
public boolean delete(int key) {
Node current = root;
Node parent = root;
boolean isLeftChild = false;
//查找删除值,找不到直接返回false
while (current.data != key) {
parent = current;
if (current.data > key) {
isLeftChild = true;
current = current.leftChild;
} else {
isLeftChild = false;
current = current.rightChild;
}
if (current == null) {
return false;
}
}
//如果当前节点没有子节点
if (current.leftChild == null && current.rightChild == null) {
if (current == root) {
root = null;
} else if (isLeftChild) {
parent.leftChild = null;
} else {
parent.rightChild = null;
}
return true;
//当前节点有一个子节点,右子节点
} else if (current.leftChild == null && current.rightChild != null) {
if (current == root) {
root = current.rightChild;
} else if (isLeftChild) {
parent.leftChild = current.rightChild;
} else {
parent.rightChild = current.rightChild;
}
return true;
//当前节点有一个子节点,左子节点
} else if (current.leftChild != null && current.rightChild == null) {
if (current == root) {
root = current.leftChild;
} else if (isLeftChild) {
parent.leftChild = current.leftChild;
} else {
parent.rightChild = current.leftChild;
}
return true;
} else {
//当前节点存在两个子节点
Node successor = getSuccessor(current);
if (current == root) {
root = successor;
} else if (isLeftChild) {
parent.leftChild = successor;
} else {
parent.rightChild = successor;
}
successor.leftChild = current.leftChild;
}
return false;
}
//获得后继节点
public Node getSuccessor(Node delNode) {
Node successorParent = delNode;
Node successor = delNode;
Node current = delNode.rightChild;
while (current != null) {
successorParent = successor;
successor = current;
current = current.leftChild;
}
//后继节点不是删除节点的右子节点,将后继节点替换删除节点
if (successor != delNode.rightChild) {
successorParent.leftChild = successor.rightChild;
successor.rightChild = delNode.rightChild;
}
return successor;
}
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.insert(50);
bt.insert(20);
bt.insert(80);
bt.insert(10);
bt.insert(30);
bt.insert(60);
bt.insert(90);
bt.insert(25);
bt.insert(85);
bt.insert(100);
bt.delete(10);//删除没有子节点的节点
bt.delete(30);//删除有一个子节点的节点
bt.delete(80);//删除有两个子节点的节点
System.out.println("最大元素:"+bt.findMax().data);
System.out.println("最小元素:"+bt.findMin().data);
System.out.println(bt.find(100));
System.out.println(bt.find(200));
System.out.println("\n-----------中序遍历-------------\n");
//中序遍历
bt.infixOrder(bt.root);
System.out.println("\n-----------前序遍历-------------\n");
//前序遍历
bt.preOrder(bt.root);
System.out.println("\n-----------后序遍历-------------\n");
//后序遍历
bt.postOrder(bt.root);
}
}
运行结果:
最大元素:100
最小元素:20
com.simoniu.binarytree.Node@7f690630
null
-----------中序遍历-------------
20 25 50 60 85 90 100
-----------前序遍历-------------
50 20 25 85 60 90 100
-----------后序遍历-------------
25 20 60 100 90 85 50