JAVA实现二叉树的基本操作

Node类:

// 二叉树节点  
public class Node {  
  
    // 数据  
    public Long data;  
  
    // 左子节点  
    public Node leftChild;  
  
    // 右子节点  
    public Node rightChild;  
  
    public Node(long data) {  
        this.data = data;  
    }  
}  


二叉树的插入、查找、遍历较为容易,删除节点较为麻烦点。

要删除的节点可分成3种情况去处理:
  (1) 该节点没有子节点:直接删除该节点即可;
  (2) 该节点只有一个节点,左子节点或者右子节点:只需将其父节点的左/右子节点的引用指向其子节点即可;
  (3) 该节点有两个子节点:需要将该节点的右子树中最小的节点替换到该节点即可。

Tree类:

public class Tree {

    // 根节点
    private Node root;

    /**
     * 插入节点
     * @param value
     */
    public void insert(long value) {
        // 创建新节点
        Node newNode = new Node(value);
        Node current = root;
        // 如果root为null,则树为空
        if(root == null) {
            root = newNode;
        } else {
            while (true) {
                // 如果当前节点数据比value要小,则向左;否则向右
                if(current.data > value) {
                    if(current.leftChild == null) {
                        current.leftChild = newNode;
                        return;
                    } else {
                        current = current.leftChild;
                    }
                } else {
                    if(current.rightChild == null) {
                        current.rightChild = newNode;
                        return;
                    } else {
                        current = current.rightChild;
                    }
                }
            }
        }
    }

    /**
     * 删除节点
     * @param value
     */
    public boolean delete(long value){

        // 当前节点
        Node current = root;
        // 父节点
        Node parent = current;
        // 标记要删除的节点,是其父节点的左子节点还是右子节点
        boolean isLeftChild = true;

        // 查找要删除的节点
        while (current.data != value) {
            parent = current;
            if(current.data > value) {
                current = current.leftChild;
                isLeftChild = true;
            } else if(current.data < value) {
                current = current.rightChild;
                isLeftChild = false;
            }
            // 如果查找不到
            if(current == null)
                return false;
        }

        /*
           要删除的节点有3种情况:
             (1) 该节点没有子节点;
             (2) 该节点只有一个节点,左子节点或者右子节点;
             (3) 该节点有两个子节点。(这种较为复杂)
          */
        if(current.leftChild == null && current.rightChild == null) {  // 该节点没有子节点;

            if(current == root) {
                root = null;
            }
            if(isLeftChild) {
                parent.leftChild = null;
            } else {
                parent.rightChild = null;
            }

        } else if(current.rightChild == null) {    // 该节点只有一个左子节点;

            if(current == root) {
                root = current.leftChild;
            }
            if(isLeftChild) {
                parent.leftChild = current.leftChild;
            } else {
                parent.rightChild = current.leftChild;
            }

        }  else if(current.leftChild == null) {    // 该节点只有一个右子节点;

            if(current == root) {
                root = current.rightChild;
            }
            if(isLeftChild) {
                parent.leftChild = current.rightChild;
            } else {
                parent.rightChild = current.rightChild;
            }

        } else {    // 该节点有两个子节点;

            /*
                 拿到中序后继的节点,也就是当前节点的右子树中数值最小的那个节点,
                 将该节点替换掉当前要被删除节点的位置上,即可得到树的平衡
              */
            Node successor = getSuccessor(current);
            if(current == root) {
                root = successor;
            } else if(isLeftChild) {
                parent.leftChild = successor;
            } else {
                parent.rightChild = successor;
            }
            successor.leftChild = current.leftChild;
        }

        return true;
    }

    // 拿到中序后继的节点,也就是当前节点的右子树中数值最小的那个节点
    private Node getSuccessor(Node delNode) {

        Node successor = delNode;
        Node successorParent = delNode;
        Node current = delNode.rightChild;

        while(current != null) {
            successorParent = successor;
            successor = current;
            current = current.leftChild;
        }

        if(successor != delNode.rightChild) {
            successorParent.leftChild = successor.rightChild;
            successor.rightChild = delNode.rightChild;
        }
        return successor;
    }

    /**
     * 按照中序遍历打印数
     */
    public void list(){

        inOrderTraverse(root);
    }

    private void inOrderTraverse(Node node) {
        if (node == null)
            return;
        inOrderTraverse(node.leftChild);
        System.out.print(node.data + " ");
        inOrderTraverse(node.rightChild);
    }

    /**
     * 查找节点
     * @param value
     */
    public Node find(long value){
        if(root == null)
            return null;
        Node current = root;
        while (current.data != value) {
            // 进行比较,查找值比当前节点小时,继续左边查找;否则右边查找
            if(current.data > value) {
                current = current.leftChild;
            } else {
                current = current.rightChild;
            }
            if(current == null)
                return null;
        }
        return current;
    }
}


测试类:

public class Test {

    public static void main(String[] args) {

        Tree tree = new Tree();

        int[] arr = new int[]{5,3,4,1,12,15,9,8,6,7,10,13,14,30};

        for (int i = 0; i < arr.length; i++) {
            tree.insert(arr[i]);
        }

        tree.list();
        System.out.println();
        System.out.println(tree.delete(12));
        tree.list();
    }
}



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值