二叉树的定义
二叉树(Binary Tree)是有限个节点的集合,这个集合可以是空集,也可以是一个根节点和两颗不相交的子二叉树组成的集合,其中一颗树叫根的左子树,另一颗树叫右子树。所以二叉树是一个递归地概念。
二叉树的遍历
二叉树的遍历分为三种:前序遍历 中序遍历 后序遍历
前序遍历:按照“根左右”,先遍历根节点,再遍历左子树 ,再遍历右子树
中序遍历:按照“左根右“,先遍历左子树,再遍历根节点,最后遍历右子树
后续遍历:按照“左右根”,先遍历左子树,再遍历右子树,最后遍历根节点
其中前,后,中指的是每次遍历时候的根节点被遍历的顺序
本文采用中序遍历、
代码时间~(@^_^@)~
/**
* 二叉树的实现
*
* @author Administrator
*
* @param <T>要进行二叉树的实现
*/
public class BinalyTree<T extends Comparable<T>> {
private class Node {
private Comparable<T> data;
private Node parent;// 保存父节点
private Node left;// 保存左子树
private Node right;// 保存又子数
public Node(Comparable<T> data) {// 构造负责数据存储
super();
this.data = data;
}
public void add(BinalyTree<T>.Node newNode) {
// TODO Auto-generated method stub
if (newNode.data.compareTo((T) this.data) <= 0) {// 比当前节点小
if (this.left == null) {// 现在没有左子树
this.left = newNode;// 保存左子树
newNode.parent = this;// 保存父节点
} else {// 需要向左边继续判断
this.left.add(newNode);// 向下继续判断
}
} else {// 比当前节点的数据更大
if (this.right == null) {// 现在没有右子树
this.right = newNode;// 保存右子树
newNode.parent = this;// 保存父节点
} else {// 有右子树
this.right.add(newNode);// 继续向下判断
}
}
}
/**
* 按照中序遍历来完成
*/
public void toArrayNode() {
// TODO Auto-generated method stub
if (this.left != null) {// 左子树不是空
this.left.toArrayNode();// 继续向下判断
}
BinalyTree.this.returnData[BinalyTree.this.foot++] = this.data;// 添加当前数据在数组里
if (this.right != null) {// 右子树不是空
this.right.toArrayNode();// 继续向下判断
}
}
public boolean containsNode(Comparable<T> data) {
// TODO Auto-generated method stub
if (data.compareTo((T) this.data) == 0) {// 比较为0则存在
return true;
} else if (data.compareTo((T) this.data) < 0) {
if (this.left != null) {// 判断是否还有节点
return this.left.containsNode(data);// 递归调用
} else {
return false;// 没有则直接返回false
}
} else {
if (this.right != null) {
return this.right.containsNode(data);
} else {
return false;
}
}
}
/**
* 操作和判断是否存在类似
*
* @param data
* @return
*/
public BinalyTree<T>.Node getRemoveNode(Comparable<T> data) {
// TODO Auto-generated method stub
if (data.compareTo((T) this.data) == 0) {
return this;
} else if (data.compareTo((T) this.data) < 0) {
if (this.left != null) {
return this.left.getRemoveNode(data);
} else {
return null;
}
} else {
if (this.right != null) {
return this.right.getRemoveNode(data);
} else {
return null;
}
}
}
}
// ------------------------以下为二叉树的实现---------------------------
private Node root;// 保存根节点
private int count = 0;// 保存数量
private Object[] returnData;// 所有数据
private int foot = 0;// 角标控制
/**
* 执行删除操作
*
* @param data
* 要删除的数据
*/
@SuppressWarnings("unchecked")
public void remove(Comparable<T> data) {
// TODO Auto-generated method stub
if (count == 0) {// 没有数据直接结束调用
return;
} else {
if (data.compareTo((T) this.root.data) == 0) {
BinalyTree<T>.Node moveNode = this.root.right;
while (moveNode.left != null) {// 找到其右子树的最小节点
moveNode = moveNode.left;
}
moveNode.left = this.root.left;
moveNode.right = this.root.right;
moveNode.parent.left = null;
this.root = moveNode;
this.count--;
} else {
Node removeNode = this.root.getRemoveNode(data);// 获取要删除的节点
if (removeNode != null) {// 没有节点数据直接结束调用
if (removeNode.left == null && removeNode.right == null) {// 被删除的数据没有左右节点
if (removeNode.parent.left == removeNode) {// 判断是父节点的左子树还是右子树
removeNode.parent.left = null;// 断开父节点的左子树
} else {
removeNode.parent.right = null;// 断开父节点的右子树
}
removeNode.parent = null;// 断开删除节点的父节点
} else if (removeNode.left != null && removeNode.right == null) {// 只有左子树的情况
removeNode.parent.left = removeNode.left;// 把父节点的左子树变成我的左子树
removeNode.left.parent = removeNode.parent;// 把我的左子树的父节点变成我的父节点
} else if (removeNode.left == null && removeNode.right != null) {
removeNode.parent.right = removeNode.right;// 父节点的右子树变成要删除节点右子树
removeNode.right.parent = removeNode.parent;// 右子树的父节点变成要删除节点的父节点
} else {// 两边都有节点
BinalyTree<T>.Node moveNode = removeNode.right;
while (moveNode.left != null) {// 找到其右子树的最小节点
moveNode = moveNode.left;
}
if (moveNode.parent.left == moveNode) {
} else {
removeNode.parent.left = moveNode;
moveNode.parent.right = null;
moveNode.left = removeNode.left;
moveNode.right = removeNode.right;
}
}
}
this.count--;
}
}
}
/**
* 判断数据是否存在
*
* @param data
* @return
*/
public boolean contains(Comparable<T> data) {
// TODO Auto-generated method stub
if (count == 0) {
return false;
}
return this.root.containsNode(data);
}
/**
* 返回所有数据
*
* @return
*/
public Object[] toArrays() {
if (count == 0) {
return null;
}
this.returnData = new Object[this.count];// 保存长度为数组长度
this.root.toArrayNode();// 由node节点自己处理数据
this.foot = 0;
return returnData;
}
/**
* 执行添加操作
*
* @param data保存的数据
*/
public void add(Comparable<T> data) {
// TODO Auto-generated method stub
if (data == null) {
throw new NullPointerException("保存的数据不允许为空!");
}
// 所有的数据本身不具备有节点关系的匹配,那么一定要将其包装在node累中
Node newNode = new Node(data);// 保存节点
if (this.root == null) {// 现在没有根节点,则现在的节点作为根节点
root = newNode;
} else {// 需要为其保存到合适的节点
this.root.add(newNode);// 交由node类负责处理
}
count++;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
/** ━━━━━━感觉自己萌萌哒━━━━━━
* ┏┓ ┏┓
* ┏┛┻━━━┛┻┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
}
我的总结:
二叉树是一个相当重要的数据结构,它的应用面非常广,并且由他改进生成了很多重要的树类数据结构,如红黑树,堆等,应用价值之高后面深入学习便有体会,因此,掌握它的基本特征和遍历方式实现是学好后续数据结构的基础,理论方面其实我们看到二叉树的形状,我们自己画图都能总结出来,但是代码实现这一块,初学者不是很好理解,树的遍历利用了递归的思想,递归的思想本质无非就是循环,方法调方法,所以,理解二叉树遍历的代码实现最好的方式就是按照它的遍历思想自己画出图来一步一步的遍历一遍,先把这个遍历过程想明白了,然后再根据递归的思想,什么时候调什么样的方法,自然就能很容易想明白了