バイナリツリーで指定されたノードを削除します

二分木のノードを削除します。

1.要件:

  • 削除したノードがリーフノードの場合は、ノードを削除します。
  • 削除されたノードが非リーフノードの場合は、サブツリーを削除します。

2.アイデア:

  • 最初にルートノードを処理します。ツリーが空かどうかを判断します。ノードが1つしかない場合は、このノードが削除するノードかどうかを判断します。
  • 二分木は一方向であるため、現在の子ノードを削除する必要があるかどうかは判断しますが、現在のノードを削除する必要があるかどうかは判断できません。
  • 現在のノードの左側の子ノードが空ではなく、左側の子ノードが削除されるノードである場合、this.left = null;およびreturn(再帰的削除の終了)
  • 現在のノードの右側の子ノードが空ではなく、右側の子ノードが削除するノードである場合は、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);
		}
		
	}
  1. 現時点では、this.leftは2を指しますが、このノードは私たちが探しているノードではありません。
  2. 次に、正しいノードの判断に進みます。現時点では、this.rightは3を指し、探しているノードではありません。
  3. ルートノード(再帰)に戻り、左側のサブツリーを再帰的に削除します。この時点で、左側のノードは2であり、空ではありません。delNode関数(pass)を入力します。this.leftは空、this.rightは空です。左側のサブツリーを再帰的に削除する試みが失敗し、右側のサブツリーを削除する試みが失敗した場合は、ノード1(再帰)に戻ります。
  4. 右側のサブツリーを再帰的に削除します。この時点で、左側のノードthis.leftは空ではなく、探している番号5です。このとき、番号3の左側は空になります。
  5. この時点で、コードはbinaryTreeのelseに戻ります
  6. mainメソッドの最後に戻ります。

おすすめ

転載: blog.csdn.net/weixin_43690348/article/details/110587591