二分木のノードを削除します。
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);
}
}
- 現時点では、this.leftは2を指しますが、このノードは私たちが探しているノードではありません。
- 次に、正しいノードの判断に進みます。現時点では、this.rightは3を指し、探しているノードではありません。
- ルートノード(再帰)に戻り、左側のサブツリーを再帰的に削除します。この時点で、左側のノードは2であり、空ではありません。delNode関数(pass)を入力します。this.leftは空、this.rightは空です。左側のサブツリーを再帰的に削除する試みが失敗し、右側のサブツリーを削除する試みが失敗した場合は、ノード1(再帰)に戻ります。
- 右側のサブツリーを再帰的に削除します。この時点で、左側のノードthis.leftは空ではなく、探している番号5です。このとき、番号3の左側は空になります。
- この時点で、コードはbinaryTreeのelseに戻ります
- mainメソッドの最後に戻ります。