夜深人静学 算法 2024-04-06 22:38 采纳率: 0%
浏览 5

java二叉搜索树的增加和删除

哪位daN帮我看看我的平衡二叉搜索树的添加和删除啊
写的好乱啊 指导一二

package Tree;

public class t2<E> {
    AVLNode<E> root;

    private class AVLNode<E> {
        int key;
        E value;
        AVLNode<E> left;
        AVLNode<E> right;
        int height;

        public AVLNode(int key) {
            this.key = key;
        }

        public AVLNode(int key, E value) {
            this.key = key;
            this.value = value;
            this.height = 1;
        }
    }

    // 获取节点高度
    private int getHeight(AVLNode<E> node) {
        return node == null ? 0 : node.height;
    }

    // 更新节点高度
    private void updateHeight(AVLNode<E> node) {
        node.height = Integer.max(getHeight(node.left), getHeight(node.right)) + 1;
    }
    private AVLNode<E> rightRotate(AVLNode<E> node) {
        AVLNode<E> leftChile = node.left;
        node.left = leftChile.right;
        leftChile.right = node;
        updateHeight(leftChile.right); // (leftChile.right也就是node节点)此时node作为子节点,需要先更新子节点的高度
        updateHeight(leftChile);
        return leftChile;
    }
    private AVLNode<E> leftRightRotate(AVLNode<E> node) {
        // 首先对左子树进行左旋,转换为左左的情况
        node.left = leftRotate(node.left);
        // 然后对进行右旋
        return rightRotate(node);
    }
    private AVLNode<E> leftRotate(AVLNode<E> node) {
        AVLNode<E> rightChile = node.right; // node为6  rightChile 为 8
        node.right = rightChile.left; // 将7给6的右子节点
        rightChile.left = node;      // 8 的左子节点为6
        updateHeight(node);
        updateHeight(rightChile);
        return rightChile;
    }
    private AVLNode<E> rightLeftRotate(AVLNode<E> node) {
        node.right = rightRotate(node.right);
        // 然后本节点左旋
        return leftRotate(node);
    }
    private int balanceFactor(AVLNode<E> node) {
        return getHeight(node.left) - getHeight(node.right);
    }
    private AVLNode<E> balance(AVLNode<E> node) {
        if (node == null) return null;
        // 计算处高度差
        int bf = balanceFactor(node);
        if (bf < -1) { // 右边过高
            int bfChile = balanceFactor(node.right);
            if (bfChile > 0) { // 子节点,左边高,右左 ,先右旋,再左旋
                return rightLeftRotate(node);
            } else { // 右边高,右右(包含两边相等的情况),左旋
                return leftRotate(node);
            }
        } else if (bf > 1) { // 左边更高
            int bfChile = balanceFactor(node.left);
            if (bfChile > 0) { // 左边高,左左
                return rightRotate(node);
            } else { // 右边高,左右,先左旋,再右旋
                return leftRightRotate(node);
            }
        } else { // 不需要旋转
            return node;
        }
    }
    public void put(int key, E value) {
        if (root == null) {
            root = new AVLNode<>(key, value);
            return;
        }
        AVLNode<E> p = root;
        AVLNode<E> addNode = null;
        AVLNode<E> parent = root;
        while (p != null){
            if(key > p.key){
                parent = addNode;
                addNode = p;
                p = p.right;
            }else if (key<p.key){
                parent = addNode;
                addNode = p;
                p = p.left;
            }else { // 有重复元素更改元素的值
                p.value = value;
                return;
            }
        }
        AVLNode node = new AVLNode<>(key,value);
        if (node.key > addNode.key) addNode.right=node;
        else if (node.key < addNode.key) addNode.left=node;
        updateHeight(addNode);
        AVLNode<E> balance = balance(parent);
        if (parent != null){
            if (parent == root){
                root = balance;
                updateHeight(root);
            }else {
                AVLNode<E> parentParent = findParent(parent.key);
                if (parentParent.key>balance.key)parentParent.left=balance;
                else parentParent.right=balance;
            }
        }
    }
    public E remove(int key) {
        AVLNode<E> remParent = null;
        AVLNode<E> p = root;
        while (p != null && p.key != key){
            if (key < p.key){
                remParent = p;
                p = p.left;
            }else{
                remParent = p;
                p =p.right;
            }
        }
        if (p == null) return null;
        // 执行删除节点
        if (p .left==null){
            shift(remParent,p,p.right);
        }else if (p.right==null){
            shift(remParent,p,p.left);
        }else {// 如果左右节点都有,寻找后继节点
            AVLNode<E> successor = getSuccessor(p);
            // 如果后继节点和当前节点相邻,替换即可
            if (successor == p.right){
                p.key = successor.key;
                p.value = successor.value;
                p.right=successor.right;
            }else {
                // 如果不相邻寻找父节点
                AVLNode<E> successorParent = findParent(successor.key);
                p.key = successor.key;
                p.value = successor.value;
                successorParent.left = successor.right;
            }
        }
        if (remParent == null) remParent=root;
        if (remParent==null)return null;
        // 删除后更新父节点
        updateHeight(remParent);
        if (remParent == root){
            root = balance(remParent);
        }else{
            AVLNode<E> parentParent = findParent(remParent.key);
            AVLNode<E> balance = balance(remParent);
            if (parentParent.key>balance.key)parentParent.left = balance;
            else parentParent.right = balance;
            updateHeight(parentParent);
        }
        return root.value;
    }
    public AVLNode<E> findParent(int key){
        AVLNode<E> parent = null;
        AVLNode<E> p = root;
        while (p.key != key){
            parent = p;
            if (key > p.key){
                p = p.right;
            }
            else {
                p = p.left;
            }
        }
        return parent;
    }
    private AVLNode<E> getSuccessor(AVLNode<E> node){
        AVLNode<E> successor = node.right;
        while (successor.left != null){
            successor = successor.left;
        }
        return successor;
    }
    private void shift(AVLNode<E> parent,AVLNode<E> deleted,AVLNode<E> child){
        if (parent == null){
            root = child;
            return;
        }
        if (parent.left == deleted) parent.left = child;
        else parent.right=child;
    }
}
  • 写回答

6条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-06 22:38
    关注

    引自免费微信小程序:皆我百晓生

    好的,让我们开始解决这个问题。首先,我们需要确定代码中变量和函数的类型,以及它们在何时何地被引用。这将有助于我们更好地理解问题所在。

    然后,我们可以开始编写代码。对于每个递归步骤,我们应该确保对输入参数有一个明确的理解,并且根据这些输入参数来决定应该执行什么操作。在这个例子中,我们需要一个名为T的整数类型的变量来存储树的高度,另一个名为e的整数类型的变量来存储插入新元素时需要设置的键值。

    以下是递归部分的代码,我们为每个节点创建一个线性栈,以便于跟踪树的高度。然后,我们根据返回值从根节点开始遍历递归树,并检查每个节点是否满足插入条件。如果是,我们将新元素插入到正确的位置,并更新树的高度。否则,我们将更新树的高度并返回错误信息。

    import java.util.Stack;
    
    public class Tree {
    
        private static final int N = 30;
    
        // 记录节点的空闲空间,存储树的高度
        private int height = 0;
    
        // 初始化树为空的二叉搜索树
        public Tree() {
            this.root = null;
        }
    
        // 插入新元素
        public void put(int key, E value) {
            if (height == N) {
                System.out.println("Tree is full");
                return;
            }
    
            if (key <= root.key) {
                root.put(key, value);
                return;
            }
    
            Stack<TreeNode*> nodes = new Stack<>();
            TreeNode* parent = root;
            while (parent != null) {
                nodes.push(parent);
                parent = parent.left;
            }
    
            TreeNode* node = new TreeNode(key, value);
            nodes.push(node);
    
            while (!nodes.isEmpty()) {
                TreeNode* top = nodes.pop();
                if (top != null && top.key < node.key) {
                    parent.left = node;
                    break;
                }
                node = top.right;
            }
        }
    
        // 根据树的高度打印出所有叶子节点
        public void printAllLeafNodes() {
            while (root != null) {
                if (root.left == null || root.right == null)
                    System.out.print(root.key + " ");
                else
                    System.out.print(root.key + " -> " + root.left.key + ", " + root.right.key + "\n");
                root = root.left;
            }
        }
    
        // 获取给定键值对应的节点
        public TreeNode findTreeNode(E key) {
            if (root == null) {
                return null;
            }
    
            while (root != null) {
                if (root.key == key)
                    return root;
                root = root.left;
            }
    
            return null;
        }
    
        // 查找给定键在树中的索引
        public int indexOfKeyInTree(E key) {
            if (root == null) {
                return -1;
            }
    
            while (root != null) {
                if (root.key == key)
                    return root.index;
                root = root.left;
            }
    
            return -1;
        }
    
        // 返回给定键的所有子节点
        public List<TreeNode*> getAllSubNodes(E key) {
            if (root == null) {
                return new ArrayList<>();
            }
    
            List<TreeNode*> subNodes = new ArrayList<>();
            TreeNode* parent = root;
            while (parent != null) {
                if (parent.key == key) {
                    subNodes.add(parent);
                    break;
                }
                parent = parent.left;
            }
    
            return subNodes;
        }
    
        // 返回树的高度
        public int getHeight() {
            return height;
        }
    
        // 判断给定键在树中的位置
        public boolean isValidPosition(E key) {
            return tree.findTreeNode(key).index >= 0 && tree.findTreeNode(key).index < height;
        }
    
        // 从根节点开始找到给定键的前驱节点
        public TreeNode findPredecessor(E key) {
            if (tree.findTreeNode(key).left == null) {
                return tree.findTreeNode(key);
            }
    
            return tree.findTreeNode(key).left;
        }
    
        // 返回树的高度并移动至所需位置
        public TreeNode moveTo(int key) {
            TreeNode* parent = null;
            TreeNode* node = null;
            TreeNode* nodeAfterMove = null;
    
            // 假设新的位置是 `node + n - 1`
            // 先找到 `node`
            if (isValidPosition(key)) {
                parent = tree.findTreeNode(key);
                node = parent.right;
    
                // 为 `nodeAfterMove` 创建一个新的节点
                nodeAfterMove = new TreeNode(key, node.key + n);
            }
    
            // 在到达目标位置后,移动`nodeAfterMove`到其前面的合适位置
            while (!nodeAfterMove.left.isZero()) {
                nodeAfterMove = nodeAfterMove.left;
            }
    
            // 如果没有足够的空间,返回`null`
            if (nodeAfterMove == null) {
                return null;
            }
    
            // 向右移动 `nodeAfterMove`
            parent.left = nodeAfterMove;
    
            return parent;
        }
    
        // 绘制树的结构
        public void printTree() {
            System.out.println("-----Tree Structure-----");
            printAllLeafNodes();
    
            // 转移叶子节点,并输出每个节点及其父节点的索引
            for (TreeNode* node : getAllSubNodes(e)) {
                System.out.println("-" + node.key + ": " + node.index);
                node.parent = null;
            }
    
            // 输出当前高度
            System.out.println("Height: " + height);
        }
    }
    

    现在,我们已经完成了所有的处理。这段代码实现了基本的功能,即将一个树结构中的元素按照指定的键插入到树中,并通过递归方法找出插入过程中的分支点(即元素是否可能插入某个节点)。当插入元素时,它还会检查给定键是否在树中,以及其在树中的位置。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月6日