java----自己实现二叉搜索树的增删查和中序遍历

二叉搜索树的中序遍历

中序遍历时不打印, 直接尾插到链表里面.

    
    // 1. 遍历二叉搜索树
    public void inOrder(TreeNode left) {
        if (this.root == null) {
            return;
        }
        inOrder(root.left);
        add(root);
        inOrder(root.right);
    }
    public void add(TreeNode node) {
        if (tail == null) {
            head = tail = node;
        } else {
            tail.right = node;
            node.left = tail;
            tail = tail.right;
        }
    }

二叉搜索树的增加

先找到需要插入的位置, 然后进行插入

    // 2. 二叉搜索树的插入
    public TreeNode insert(char val) {
        if (root == null) {
            root = new TreeNode(val);
            return root;
        }
        TreeNode cur = root;
        TreeNode pre = null;
        int cmp = 0;
        while (cur != null) {
            cmp = compare(val, cur.val);
            if (cmp < 0) {
                pre = cur;
                cur = cur.left;
            } else if (cmp > 0) {
                pre = cur;
                cur = cur.right;
            } else {
                // 插入失败
                return root;
            }
        }
        if (cmp < 0) {
            pre.left = new TreeNode(val);
        } else {
            pre.right = new TreeNode(val);
        }
        return root;
    }

二叉搜索树的删除

先找到要删除的结点, 然后借助 removeInternal 函数进行删除

    // 3. 二叉搜索树的删除
    public boolean remove(char c) {
        // 先找到该节点
        TreeNode cur = root;
        TreeNode pre = null;
        while (cur != null) {
            int cmp = compare(c, cur.val);
            if (cmp == 0) {
                removeInternal(cur, pre);
                return true;
            } else if (cmp < 0) {
                pre = cur;
                cur = cur.left;
            } else {
                pre = cur;
                cur = cur.right;
            }
        }
        return false;
    }

删除 node 节点时, 分为四种情况(pre 是要删除结点的父节点)
<1>要删除的结点没有左子树和右子树
①要删除的结点为根节点

if (node == root) {
    root = null;
}

②要删除的结点不为根节点

// 如果父节点的左孩子是要删除的结点 node 
if (node == pre.left) {
    pre.left = null;
} else {
// 如果父节点的右孩子是要删除的结点 node 
  	pre.right = null;
}

<2>要删除的结点有左子树和无右子树
①要删除的结点为根节点

if (node == root) {
    root = root.left;
}

②要删除的结点不为根节点

// 如果父节点的左孩子是要删除的结点 node 
if (node == pre.left) {
    pre.left = node.left;
} else {
// 如果父节点的右孩子是要删除的结点 node 
    pre.right = node.left;
}

<3>要删除的结点没有左子树和有右子树
①要删除的结点为根节点

if (node == root) {
    root = root.right;
}

②要删除的结点不为根节点

// 如果父节点的左孩子是要删除的结点 node 
if (node == pre.left) {
    pre.left = node.right;
} else {
// 如果父节点的右孩子是要删除的结点 node 
    pre.right = node.right;
}

<4>要删除的结点有左子树和右子树
找左子树中最大的结点(左子树中最右边的结点), 将该节点与要删除结点进行替换, 然后删除该节点(左子树中最右边的结点).

    private void removeInternal(TreeNode node, TreeNode pre) {
        if (node.left == null && node.right == null) {
            if (node == root) {
                root = null;
            } else if (node == pre.left) {
                pre.left = null;
            } else {
                pre.right = null;
            }
        } else if (node.left != null && node.right == null) {
            if (node == root) {
                root = root.left;
            } else if (node == pre.left) {
                pre.left = node.left;
            } else {
                pre.right = node.left;
            }
        } else if (node.left == null && node.right != null) {
            if (node == root) {
                root = node.right;
            } else if (node == pre.left) {
                pre.left = node.right;
            } else {
                pre.right = node.right;
            }
        } else {
            // 找左子树中最大的与要删除的结点的值进行替换
            TreeNode parent = node;
            TreeNode child = node.left;
            // 一直往右走找值最大的结点 child
            while (child.right != null) {
                parent = child;
                child = child.right;
            }
            // 进行替换
            node.val = child.val;
            // 删除被替换的结点
            // 如果要删除结点的左子树没有右节点
            if (parent == node) {
                parent.left = child.left;
            } else {
            // 如果要删除结点的左子树有右节点
                parent.right = child.left;
            }
        }
    }

二叉搜索树的查找

    // 4. 查找
    public TreeNode find(TreeNode root, char c) {
        TreeNode cur = root;
        int cmp = 0;
        while (cur != null) {
            cmp = compare(c, cur.val);
            if (cmp < 0) {
                cur = cur.left;
            } else if (cmp > 0) {
                cur = cur.right;
            } else {
                return cur;
            }
        }
        return null;
    }

完整代码

public class BST {
    TreeNode root = null;
    TreeNode head = null;
    TreeNode tail = null;


    // 二叉搜索树的中序遍历是有序的
    // 1. 遍历二叉搜索树
    public void inOrder(TreeNode left) {
        if (this.root == null) {
            return;
        }
        inOrder(root.left);
        add(root);
        inOrder(root.right);
    }
    public void add(TreeNode node) {
        if (tail == null) {
            head = tail = node;
        } else {
            tail.right = node;
            node.left = tail;
            tail = tail.right;
        }
    }
    // 2. 二叉搜索树的插入
    public TreeNode insert(char val) {
        if (root == null) {
            root = new TreeNode(val);
            return root;
        }
        TreeNode cur = root;
        TreeNode pre = null;
        int cmp = 0;
        while (cur != null) {
            cmp = compare(val, cur.val);
            if (cmp < 0) {
                pre = cur;
                cur = cur.left;
            } else if (cmp > 0) {
                pre = cur;
                cur = cur.right;
            } else {
                // 插入失败
                return root;
            }
        }
        if (cmp < 0) {
            pre.left = new TreeNode(val);
        } else {
            pre.right = new TreeNode(val);
        }
        return root;
    }

    private int compare(char val, char val1) {
        return val - val1;
    }

    // 3. 二叉搜索树的删除
    public boolean remove(char c) {
        // 先找到该节点
        TreeNode cur = root;
        TreeNode pre = null;
        while (cur != null) {
            int cmp = compare(c, cur.val);
            if (cmp == 0) {
                removeInternal(cur, pre);
                return true;
            } else if (cmp < 0) {
                pre = cur;
                cur = cur.left;
            } else {
                pre = cur;
                cur = cur.right;
            }
        }
        return false;
    }

    private void removeInternal(TreeNode node, TreeNode pre) {
        if (node.left == null && node.right == null) {
            if (node == root) {
                root = null;
            } else if (node == pre.left) {
                pre.left = null;
            } else {
                pre.right = null;
            }
        } else if (node.left != null && node.right == null) {
            if (node == root) {
                root = root.left;
            } else if (node == pre.left) {
                pre.left = node.left;
            } else {
                pre.right = node.left;
            }
        } else if (node.left == null && node.right != null) {
            if (node == root) {
                root = node.right;
            } else if (node == pre.left) {
                pre.left = node.right;
            } else {
                pre.right = node.right;
            }
        } else {
            // 找左子树中最大的与要删除的结点的值进行替换
            TreeNode parent = node;
            TreeNode child = node.left;
            // 一直往右走找最大的
            while (child.right != null) {
                parent = child;
                child = child.right;
            }
            // 进行替换
            node.val = child.val;
            // 删除被替换的结点
            if (parent == node) {
                parent.left = child.left;
            } else {
                parent.right = child.left;
            }
        }
    }

    // 4. 查找
    public TreeNode find(TreeNode root, char c) {
        TreeNode cur = root;
        int cmp = 0;
        while (cur != null) {
            cmp = compare(c, cur.val);
            if (cmp < 0) {
                cur = cur.left;
            } else if (cmp > 0) {
                cur = cur.right;
            } else {
                return cur;
            }
        }
        return null;
    }
}

测试代码

public class Test {
    public static void main(String[] args) {
        TreeNode root = new TreeNode('D');
        root.left = new TreeNode('B');
        root.right = new TreeNode('F');
        root.left.left = new TreeNode('A');
        root.left.right = new TreeNode('C');
        BST bst = new BST();
        bst.insert('A');
        System.out.println(bst.remove('A'));
        System.out.println(bst.insert('0'));
        System.out.println(bst.root);
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值