概述
二叉树是一种非线性数据结构。它具有链表的优点,插入与删除的效率高,同时他的特殊结构再结合一定的节点排序规律,使他的查找效率到达有序数组。但是也并不意味着二叉树可以替代单链表和数组,结合不同的应用场景使用合适的数据结构。
二叉树是有二叉树节点组成,一个节点包含自身的数据和左右子节点的指针,一个二叉树至少有一个根节点,
实现
- TreeNode结构包含value、左节点、右节点,构造函数给节点value赋值。
class TreeNode{
int value;
TreeNode left;
TreeNode right;
public TreeNode(int value){
this.value = value;
}
}
- 二叉树的前中后三种遍历。
- 前序遍历:自己——>左子节点——右子节点
- 中序遍历:左子节点——>自己——右子节点
- 前序遍历:左子节点——右子节点——>自己
//前序遍历输出
public void preOrder(){
if(this==null){
return;
}
System.out.print(" "+ this.value);
if(this.left!=null){
this.left.preOrder();
}
if(this.right!=null){
this.right.preOrder();
}
}
//中序遍历输出
public void midOrder(){
if(this==null){
return;
}
if(this.left!=null){
this.left.midOrder();
}
System.out.print(" "+ this.value);
if(this.right!=null){
this.right.midOrder();
}
}
//后序遍历输出
public void lastOrder(){
if(this==null){
return;
}
if(this.left!=null){
this.left.lastOrder();
}
if(this.right!=null){
this.right.lastOrder();
}
System.out.print(" "+ this.value);
}
- 插入规则是满足二叉排序树,二叉排序树的排序规则是一个节点的左子节点小于它,右子节点大于它。
//插入
public void add(TreeNode node){
if(node == null){
return;
}
if(node.value<this.value){
if(this.left !=null){
this.left.add(node);
}else{
this.left = node;
}
}else{
if(this.right!=null){
this.right.add(node);
}else{
this.right= node;
}
}
}
- 删除节点,节点的删除以待删除节点的子节点个数0、1、2分为3种情况。因为根节点没有父节点,这3每种情况又得根据否是根节点进行讨论。
//删除
public TreeNode delete(int value){
TreeNode root = this;
TreeNode deNode = this; //待删除节点
boolen isLeft; //是preNode的左节点
TreeNode preNode; //待删除节点的父节点
//先查找待删除节点、待删除节点的前一节点、待删除节点是前一节点的左子节点还是右子节点。
for(;;){
if(deNode==null){
throw new RuntimeException("二叉树中无此节点");
}
if(value==deNode.value){ //找到节点
break;
}
if(value<deNode.value){
preNode = deNode;
isLeft = true;
deNode = deNode.left;
}
if(value>deNode.value){
preNode = deNode;
isLeft = false;
deNode = deNode.right;
}
}
//待删除节点无子节点
if(deNode.left==null&&deNode.right==null){
if(preNode == null){
throw new RuntimeException("根节点被删除,树为空");
}else{
if(isLeft){
preNode.left = null;
}else{
preNode.right = null;
}
}
}else if(deNode.left==null&&deNode.right!=null){ //仅有右子节点
if(preNode ==null){
return deNode.right;
}else{
if(isLeft){
preNode.left = deNode.right;
}else{
preNode.right = deNode.right;
}
}
}else if(deNode.left!=null&&deNode.right!=null){ //仅有左子节点
if(preNode ==null){
return deNode.right;
}else{
if(isLeft){
preNode.left = deNode.left;
}else{
preNode.right = deNode.left;
}
}
}else{ //有左右子节点
treeNode max = selectMax(deNode.left); //找到左子树虽大节点替换待删除节点
if(preNode ==null){
root = max;
nodeMax.left = deNode.left;
nodeMax.right = deNode.right;
}else{
preNode.left = max;
max.left = deNode.left;
max.right = deNOde.right;
}
}
return root;
}
//查找最大节点,并断开连接
public TreeNode selectMax(TreeNode node){
TreeNode temp = node;
TreeNode preTemp;
for(;;){
if(node.right!=null){
preTemp = temp;
temp = temp.rigth;
}else{
preTemp.right = null
return temp;
}
}
}