二叉树删除节点:
1.要求:
- 如果删除的节点是叶子结点,则删除该结点。
- 如果删除的节点是非叶子结点,则删除该子树。
2.思路:
- 首先处理根节点:判断树是否为空,如果只有一个结点,判断此结点是不是要删除的结点。
- 因为二叉树是单向所以我们判断当前子结点是否需要删除结点,而不能去判断当前这个结点是不是需要删除的节点。
- 如果当前结点的左子结点不为空,并且左子结点就是要删除的结点就将this.left = null;并返回(结束递归删除)
- 如果当前结点的右子结点不为空,并且右子结点就是要删除的结点,就将this.right = null;并返回(结束递归删除)
- 如果上面步骤没有删除那么就需要向左右子树进行递归删除。
3.代码演示:
(1)、主方法:
public class binaryTreeDemo {
public static void main(String[] args) {
//先创建一个二叉树
BinaryTree binaryTree = new BinaryTree();
//创建需要的结点
HeroNode root = new HeroNode(1,"1");
HeroNode node2 = new HeroNode(2,"2");
HeroNode node3 = new HeroNode(3,"3");
HeroNode node4 = new HeroNode(4,"4");
HeroNode node5 = new HeroNode(5,"5");
//说明:手动创建二叉树
root.setLeft(node2);
root.setRight(node3);
node3.setLeft(node5);
node3.setRight(node4);
//测试:
binaryTree.setRoot(root);
System.out.println("删除前,前序遍历");
binaryTree.centerOrder();
binaryTree.del(5);
System.out.println("删除后,前序遍历");
binaryTree.centerOrder();
}
}
(2)、定义一个二叉树:
//定义一个二叉树
class binaryTree{
//根节点
private Node root;
//一个set方法
public void setRoot(Node root) {
this.root = root;
}
//删除结点
public void del(int no){
if(this.root!=null){
//是否只有一个结点,这里立即判断root是不是就是要删除结点
if(root.getNo() == no) {
root = null;
}else {
//递归删除
root.delNode(no);
}
}else{
System.out.println("空树不能删除");
}
}
//前序遍历
public void preOrder() {
if(this.root != null) {
this.root.preOrder();
}else {
System.out.println("二叉树为空,无法遍历");
}
}
}
(3)、创建结点:
//创建结点
class Node{
private int no;
private String name;
private HeroNode left;//默认null
private HeroNode right;//默认null
public HeroNode(int no,String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
@Override
public String toString() {
return "HeroNode [no=" + no + ", name=" + name + "]";
}
//递归删除节点
//1、如果删除的结点是叶子结点,则删除该结点
//2、如果删除的结点是非叶子结点,则删除该子树
public void delNode(int no){
//判断当前结点的左子结点是否为空且是否是要删除的结点
if(this.left!=null && this.left.no==no){
this.left = null;
return;
}
//判断当前结点的右子结点是否为空且是否是要删除的结点
if(this.right!=null && this.right.no==no){
this.right = null;
return;
}
//向左子树进行递归删除
if(this.left!=null) {
this.left.delNode(no);
}
//向右子树进行递归删除
if(this.right!=null) {
this.right.delNode(no);
}
}
//编写前序遍历的方法
public void preOrder() {
System.out.println(this);//先输出父结点
//递归向左子树前序
if(this.left != null) {
this.left.preOrder();
}
//递归向右子树前序遍历
if(this.right != null) {
this.right.preOrder();
}
}
}
代码分析:
del方法: 以当前根结点1为例首先进入del方法中判断当前结点是否为空和是否是要查找的结点,如果不是则进入delNode方法中。
//删除结点
public void delNode(int no){
if(this.root!=null){
//是否只有一个结点,这里立即判断root是不是就是要删除结点
if(root.getNo() == no) {
root = null;
}else {
//递归删除
root.delNode(no);
}
}else{
System.out.println("空树不能删除");
}
}
delNode方法:
public void delNode(int no) {
//如果当前结点的左子结点不为空,并且左子结点就是要删除的结点,就将this.left = null,并且就返回(结束递归删除)
if(this.left!=null && this.left.no == no) {
this.left = null;
return;
}
//如果当前结点的右子结点不为空,并且右子结点就是要删除的结点,就将this.right = null,并且就返回(结束递归删除)
if(this.right!=null && this.right.no == no) {
this.right = null;
return;
}
//向左子树进行递归删除
if(this.left!=null) {
this.left.delNode(no);
}
//向右子树进行递归删除
if(this.right!=null) {
this.right.delNode(no);
}
}
- 此时this.left指的是2,但是此结点不是我们要查找的结点。
- 接着进行右结点判断,此时this.right指的是3不是我们要查找的结点。
- 回到root结点(归),向左子树进行递归删除,此时左结点为2不为空进入delNode函数(递),this.left为空、this.right为空,向左子树尝试递归删除失败、向右子树尝试递归删除失败,则回到1号结点(归)。
- 向右子树进行递归删除,此时左结点this.left不为空并且是我们要查找的数5,此时就会将3号的左边置空。
- 此时代码回到binaryTree里面的else
- 回到主方法结束。