二叉树实现基本原理:取第一个数据为保存的根节点,小于等于根节点的数据要放在节点的左子树,大于节点的数据要放在节点的右子树。
如果要进数据检索,就需要进行节点的判断,时间复杂度是O(logn)。
数据查询三种形式:前序遍历(根-左-右)、中序遍历(左-根-右)、后续遍历(左-右-根)。以中序遍历为例,遍历顺序:10、20、25、30、38、50、80、100.
二叉树的基础实现
实现二叉树的处理之中最为关键性的问题在于数据的保存,而且数据由于牵扯到对象比较的问题,那么一定要有比较器的支持,而比较器首选的一定就是Comparable。
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
// TODO Auto-generated method stub
return this.age - o.age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
随后如果要想进行数据的保存,首先一定需要有一个节点类。节点类里面由于牵扯到数据的保存问题,所以使用到Comparable(可以区分大小)
package demo;
import java.util.Arrays;
import java.util.Comparator;
public class JavaDemoComparable {
public static void main(String[] args) {
BinaryTree<Person> tree = new BinaryTree<Person>();
tree.add(new Person("Cherry-17", 17));
tree.add(new Person("Cherry-10", 10));
tree.add(new Person("Cherry-27", 27));
tree.add(new Person("Cherry-87", 87));
tree.add(new Person("Cherry-57", 57));
tree.add(new Person("Cherry-37", 37));
System.out.println(Arrays.toString(tree.toArray()));
}
}
class PersonCompatator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
// TODO Auto-generated method stub
return o1.getAge() - o2.getAge();
}
}
/**
* 实现二叉树操作
*
* @author
*
* @param <T> 要进行二叉树的实现
*/
class BinaryTree<T extends Comparable<T>> {
private class Node {
private Comparable<T> data;// 存放Comparable,可以比较大小
private Node parent;// 保存父节点
private Node left;// 保存左子树
private Node right;// 保存右子树
public Node(Comparable<T> data) {// 构造方法直接进行数据的存储
this.data = data;
}
/**
* 实现节点数据的实当位置的存储
*
* @param newNode 创建新的节点
*/
public void addNode(Node newNode) {
if (newNode.data.compareTo((T) this.data) <= 0) {// 比当前节点数据小
if (this.left == null) {// 没有左子树
this.left = newNode;// 保存左子树
newNode.parent = this;// 保存父节点
} else {
this.left.addNode(newNode);// 继续向下判断
}
} else {// 比根节点的数据大
if (this.right == null) {
this.right = newNode;
newNode.parent = this;
} else {
this.right.addNode(newNode);
}
}
}
/**
* 实现所有数据的获取处理,按照中序遍历的形式来完成
*/
public void toArrayNode(){
if(this.left != null) {
this.left.toArrayNode();
}
BinaryTree.this.returnData[BinaryTree.this.foot++] = this.data ;
if (this.right != null) {
this.right.toArrayNode();
}
}
}
// ---------一下为二叉树的功能实现----------
private Node root;// 保存根节点
private int count;// 保存数据个数
private Object [] returnData; //返回数据
private int foot = 0;//脚标控制
/**
* 进行数据的保存
*
* @param data 要保存的数据内容
* @exception NullPointerException 保存数据为空时抛出异常
*/
public void add(Comparable<T> data) {
if (data == null) {
throw new NullPointerException("保存的数据不允许为空 ");
}
// 所有的数据本身不具备有节点关系的匹配,那么一定要将其包装在Node类之中
Node newNode = new Node(data);
if (this.root == null) {// 现在没有根节点
this.root = newNode;
} else {// 需要为其保存到一个合适的节点
this.root.addNode(newNode);// 交由Node类负责处理
}
this.count++;
}
/**
* 以对象数组的形式返回全部数据,如果没有数据返回null
* @return 返回全部数据
*/
public Object[] toArray() {
if(this.count == 0) {
return null;
}
this.returnData = new Object[this.count];//保存长度为数组长度
this.foot = 0;//脚标清零
this.root.toArrayNode();//直接通过Node类负责
return this.returnData ;
}
}
class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
// TODO Auto-generated method stub
return this.age - o.age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]\n";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
#[Person [name=Cherry-10, age=10]
, Person [name=Cherry-17, age=17]
, Person [name=Cherry-27, age=27]
, Person [name=Cherry-37, age=37]
, Person [name=Cherry-57, age=57]
, Person [name=Cherry-87, age=87]
]
载进行数据添加的时候只是实现了节点关系的保存,而这种关系保存后的结果就是所有的数据都是有序排列。
数据删除
二叉树之中的数据删除操作是非常复杂的,因为在进行数据删除的时候需要考虑的情况较多:
1:如果待删除节点没有子节点,那么直接删掉即可;
2:如果待删除结点只有一个子节点,那么直接删掉,并用其子节点取顶替它;
此时考虑两种情况:
-
只有一个左子树。
-
只有一个右子树。
3:如果待删除节点有两个子节点,这种情况比较复杂:首选找出它的后继节点,然后处理"后继节点"和"被删除节点的父节点"之间的关系,最后处理“后继节点的子节点”和“被删除节点的子节点”之间的关系。