二叉树学习简介
二叉树是数据结构的一种。
二叉树的特点:左子树小于父节点,右 子树大于父节点
二叉树与链表比较相似,在链表的基础上给内部类增加了两个节点
二叉树基本方法有增加节点,删除节点,返回节点,返回节点数量
二叉树的删除操作是理解的重中之重
二叉树有三种遍历操作:先序遍历,中序遍历,后序遍历。
二叉树的输出节点操作采用中序遍历,中序遍历使数据按从小到大的顺序依次输出。
二叉树—增加节点操作
二叉树增加节点从两方面考虑:
- 二叉树为空,将要增加节点直接设为根节点
- 二叉树已有节点,这里再分两种情况:
- 新增节点小于本次对比的数据。此时查看本次节点的左子树,若左子树为空,则将新增节点设为本次节点的左子树;若不为空,本次节点的左子树递归调用方法。
- 新增节点大于本次对比的数据。此时查看本次节点的右子树,若右子树为空,则将新增节点设为本次节点的右子树;若不为空,本次节点的右子树递归调用方法。
增加节点—代码实现:
class BinaryTree<T extends Comparable>{
private class Node{
private Comparable<T> data;
private Node parent; // 该节点的父节点
private Node left; // 该节点左子树的根节点
private Node right; // 该节点右子树的根节点
public Node(Comparable<T> t) {
this.data = t;
}
//判断数据大小,决定新增节点在该二叉树中的位置
public void addNode(Node newNode) {
if(this.data.compareTo((T)newNode.data)>0) {
if(this.left == null) {
this.left = newNode;
this.left.parent = this;
}else {
this.left.addNode(newNode);
}
}else {
if(this.right == null) {
this.right = newNode;
this.right.parent = this;
}else {
this.right.addNode(newNode);
}
}
}
}
private Node root; // 根节点
private int count; // 节点计数属性
//二叉树为空,新增节点设为根节点,不为空则调用addNode方法实现增加操作
public void add(Comparable<T> data) {
if(data == null) {
throw new NullPointerException("保存数据不允许为空");
}
Node newNode = new Node(data);
if(this.root == null) {
this.root = newNode;
}else {
this.root.addNode(newNode);
}
this.count++;
}
}
二叉树—输出节点操作
二叉树的输出节点操作分两方面考虑:
- 二叉树为空,返回空值
- 二叉树不为空,中序遍历二叉树
何为中序遍历?三步操作:
- 查看当前节点有无左子树,有则遍历,没有则开始步骤二
- 当前节点无左子树,输出该节点,然后开始步骤三
- 查看当前节点有无右子树,有则开始步骤一,没有则输出上一节点并跳至步骤三
输出节点—代码实现(这里将增加节点的代码放在一起):
class BinaryTree<T extends Comparable>{
private class Node{
private Comparable<T> data;
private Node parent;
private Node left;
private Node right;
public Node(Comparable<T> t) {
this.data = t;
}
public void addNode(Node newNode) {
if(this.data.compareTo((T)newNode.data)>0) {
if(this.left == null) {
this.left = newNode;
this.left.parent = this;
}else {
this.left.addNode(newNode);
}
}else {
if(this.right == null) {
this.right = newNode;
this.right.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 int foot = 0;
private Object[] returndata;
public void add(Comparable<T> data) {
if(data == null) {
throw new NullPointerException("保存数据不允许为空");
}
Node newNode = new Node(data);
if(this.root == null) {
this.root = newNode;
}else {
this.root.addNode(newNode);
}
this.count++;
}
//二叉树为空则返回null,不为空交给toArrayNode实现
public Object[] toArray() {
if(this.count == 0) {
return null;
}
this.foot = 0;
this.returndata = new Object[this.count];
this.root.toArrayNode();
return this.returndata;
}
}
二叉树—删除节点操作
二叉树删除节点考虑三种情况:
- 待删除节点为叶子节点,断开该节点的父节点与它的联系
- 待删除节点只有一个子树,将该节点的父节点与其子树联系
- 待删除节点左右子树都存在,挑选该节点右子树的最小节点或左子树的最大节点,将其的数据赋值给该节点,并断开该节点的父节点与他的联系
删除节点(含增加节点,输出节点所有代码)—代码实现:
class BinaryTree<T extends Comparable>{
private class Node{
private Comparable<T> data;
private Node parent;
private Node left;
private Node right;
public Node(Comparable<T> t) {
this.data = t;
}
public void addNode(Node newNode) {
if(this.data.compareTo((T)newNode.data)>0) {
if(this.left == null) {
this.left = newNode;
this.left.parent = this;
}else {
this.left.addNode(newNode);
}
}else {
if(this.right == null) {
this.right = newNode;
this.right.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();
}
}
public Node getremoveNode(Comparable<T> data) {
if(this.data.compareTo((T)data) == 0) {
return this;
}
if(this.data.compareTo((T)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;
private int foot = 0;
private Object[] returndata;
public void add(Comparable<T> data) {
if(data == null) {
throw new NullPointerException("保存数据不允许为空");
}
Node newNode = new Node(data);
if(this.root == null) {
this.root = newNode;
}else {
this.root.addNode(newNode);
}
this.count++;
}
public Object[] toArray() {
if(this.count == 0) {
return null;
}
this.foot = 0;
this.returndata = new Object[this.count];
this.root.toArrayNode();
return this.returndata;
}
//由getremoveNode方法找到待删除节点,再依据上面我说的三种情况分别处理
public void remove(Comparable<T> data) {
Node removeNode = this.root.getremoveNode(data);
if(removeNode == null) {
System.out.println("不存在");
}
if(this.root.data.compareTo((T)data) == 0) {
Node moveNode = this.root.right;
while(moveNode.left != null) {
moveNode = moveNode.left;
}
moveNode.parent.left = null;
this.root.data = moveNode.data;
}else if(removeNode.left == null && removeNode.right == null){
if(removeNode.parent.left.data == removeNode.data) {
removeNode.parent.left = null;
}else {
removeNode.parent.right = null;
}
}else if(removeNode.left != null && removeNode.right == null) {
removeNode.parent.left = removeNode.left;
removeNode.left.parent = removeNode.parent;
}else if(removeNode.right != null && removeNode.left == null) {
removeNode.parent.left = removeNode.right;
removeNode.right.parent = removeNode.parent;
}else {
Node moveNode = removeNode.right;
while(moveNode.left != null) {
moveNode = moveNode.left;
}
removeNode.data = moveNode.data;
moveNode.parent.left = null;
}
this.count--;
}
}
二叉树—返回节点数操作
二叉树的返回节点操作,如果还有印象我们设置了节点计数属性,return返回该属性即可。