二叉搜索树(实现增删查,前中后层次遍历、获取深度和结点数量)

俺一直觉得二叉树是一个天然适合用递归处理的结构,只能从顶开始,面前只有两条路,不断将问题细化直到最底,然后再倒回去选择另一种路。
而二叉搜索树的结构就是在二叉树的基础上,多了一个规则,某结点的左子树的结点总是小于它,右子树的结点总是大于它,且结点唯一 [1]
写一个二叉搜索树的结构,最核心的地方就是查找,如果会查找了,俺感觉其他都差不多。

二叉树

static class TreeNode<T extends Comparable<? super T>> {
        T val;
        TreeNode<T> left;
        TreeNode<T> right;

        TreeNode(T t){
            val = t;
        }
    }

查找

根据那条规则[1],我们知道,如果要找一个值在树中是否存在,小了就找左树,大了就找右树,而且不用回溯的,找不到就是找不到,倒回去也找不到。


	private TreeNode serch(T val){
        if(isEmploy()||val==root.val){
        //Empty,emmm拼错了,懒得改也
            return root;
        }
        return serch(root,val);
    }

    private TreeNode  serch(TreeNode<T> t,T val){
        if(t==null){
            return null;
        }
        if(t.val.compareTo(val)==0){
            return t;
        }

        if(t.val.compareTo(val)>0){
            return serch(t.left,val);
        }else {
            return serch(t.right,val);
        }
    }

插入

跟查找类似,如果存在于树中,就不用插了,如果不存在,那就找到合适的地方,找到属于它的那个空结点。

public void insert(T val){
        if(exist(val)){//如果存在于子树
            return;
        }else if(isEmploy()){
            root = new TreeNode<>(val);
        }else{
            insert(val,root);
        }
        size++;
    }
private void insert(T val,TreeNode<T> root){
        if(root.val.compareTo(val)<0){
            if(root.right==null){
                root.right = new TreeNode<>(val);
                return;
            }
            insert(val,root.right);
        }else {
            if(root.left==null){
                root.left = new TreeNode<>(val);
                return;
            }
            insert(val,root.left);
        }
    }

删除

注意删除和前两个操作略有差异,由于删除后我们需要调整结点。有三种情况(当然也阔能树中根本没那个结点)

  1. 该结点只有左子树:用左子树的首个结点替换它
  2. 只有右子树:用右子树的首个结点替换它
  3. 都有:这种就有点难顶了,这里我们采用的方式是找一个肯定会大于它左子树所有值又小于它右子树所有值的结点来替换它。有两种选择:1.左子树的最右结点 2.右子树的最左结点。这里我们采用的第二种
    不过注意这里它涉及到回溯了(当然如果能保存它的父节点的话倒也不用回溯),因为需要将更改后的子树与其父节点连接起来。
public void delete(T val){
        root = delete(root,val);
        size--;
    }
    private TreeNode delete(TreeNode<T> root, T val) {
        if(root==null){
            return null;
        }
        if(root.val.compareTo(val)>0){
            root.left = delete(root.left,val);
        }else if(root.val.compareTo(val)<0){
            root.right = delete(root.right,val);
        }else{
            if(root.left!=null||root.right!=null){
                TreeNode<T> temp = root.left;
                //找到最右结点
                while(temp.right!=null){
                    temp = temp.right;
                }
                root.val = temp.val;
                //为了将树连起来,如果有指针的话倒是阔以直接赋值为null
                root.left = linked(root.left);
            }else if(root.left!=null){
                root = root.left;
            }else if(root.right!=null){
                root = root.right;
            }else {
                root = null;
            }
        }
        return root;
    }
    private TreeNode<T> linked(TreeNode treeNode){
        if(treeNode.right==null){
            return treeNode.left;
        }
        treeNode.right = linked(treeNode.right);
        return treeNode;
    }

遍历

有四种遍历方式:

	private enum ModeEnum {
        pre("pre"),mid("mid"),after("after"),levelOrder("levelOrder");
        private String mode;
        ModeEnum(String mode){
            this.mode = mode;
        }
    }
    public List<T> toList(String s){
        if(isEmploy()){
            return null;
        }
        ModeEnum mode = ModeEnum.valueOf(s);
        List<T> list = new ArrayList<>();
        switch (mode){
            case mid:
                mid(root,list);
                break;
            case pre:
                pre(root,list);
                break;
            case after:
                after(root,list);
                break;
            case levelOrder:
                levelOrder(root,list);
                break;
            default:
                mid(root,list);
        }
        return list;
    }

前中后遍历很简单,用递归的方式写的话,都是基于深搜+回溯的思想,每个结点都是父节点 ,不过它的儿子阔能是null而已。

private void after(TreeNode<T> root, List<T> list) {
        if(root==null){
            return;
        }
        after(root.left,list);
        after(root.right,list);
        list.add(root.val);
    }

    private void pre(TreeNode<T> root, List<T> list) {
        if(root==null){
            return;
        }
        list.add(root.val);
        pre(root.left,list);
        pre(root.right,list);
    }


    private void mid(TreeNode<T> node,List<T> list){
        if(node==null){
            return;
        }
        mid(node.left,list);
        list.add(node.val);
        mid(node.right,list);
    }

层次遍历,比较自然的想法就是广度优先了。要尊老嘛(不是),父辈的儿子结点肯定优先于子辈的儿子,要实现这种操作使用队列呀。

private void levelOrder(TreeNode<T> root, List<T> list) {
        Queue<TreeNode<T>> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode<T> t = queue.poll();
            if(t.left!=null){
                queue.offer(t.left);
            }
            if(t.right!=null){
                queue.offer(t.right);
            }
            list.add(t.val);
        }
    }

最大深度

也是深搜+回溯的思想,一条一条的路线找,找到更长的路线就更新。
(广搜也阔以呀,不过需要给记录下存入队列的结点所属的层数,加入它的子节点时就要在当前基础上+1了,从上到下的数,深搜就是从下往上的数)

	public int depth(){
        return depth(root);
    }
    private int depth(TreeNode<T> node){
        if(node==null){
            return 0;
        }
        return Math.max(depth(node.left),depth(node.right))+1;
    }

完整代码

import java.util.*;
public class SerchTree <T extends Comparable<? super T>> {
    private TreeNode root;
    private int size;
    private enum ModeEnum {
        pre("pre"),mid("mid"),after("after"),levelOrder("levelOrder");
        private String mode;
        ModeEnum(String mode){
            this.mode = mode;
        }
    }
    public int depth(){
        return depth(root);
    }
    private int depth(TreeNode<T> node){
        if(node==null){
            return 0;
        }
        return Math.max(depth(node.left),depth(node.right))+1;
    }
    public List<T> toList(String s){
        if(isEmploy()){
            return null;
        }
        ModeEnum mode = ModeEnum.valueOf(s);
        List<T> list = new ArrayList<>();
        switch (mode){
            case mid:
                mid(root,list);
                break;
            case pre:
                pre(root,list);
                break;
            case after:
                after(root,list);
                break;
            case levelOrder:
                levelOrder(root,list);
                break;
            default:
                mid(root,list);
        }
        return list;
    }
    private void levelOrder(TreeNode<T> root, List<T> list) {
        Queue<TreeNode<T>> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode<T> t = queue.poll();
            if(t.left!=null){
                queue.offer(t.left);
            }
            if(t.right!=null){
                queue.offer(t.right);
            }
            list.add(t.val);
        }
    }
    private void after(TreeNode<T> root, List<T> list) {
        if(root==null){
            return;
        }
        after(root.left,list);
        after(root.right,list);
        list.add(root.val);
    }
    private void pre(TreeNode<T> root, List<T> list) {
        if(root==null){
            return;
        }
        list.add(root.val);
        pre(root.left,list);
        pre(root.right,list);
    }
    private void mid(TreeNode<T> node,List<T> list){
        if(node==null){
            return;
        }
        mid(node.left,list);
        list.add(node.val);
        mid(node.right,list);
    }
    static class TreeNode<T extends Comparable<? super T>> {
        T val;
        TreeNode<T> left;
        TreeNode<T> right;

        TreeNode(T t){
            val = t;
        }
    }
    public SerchTree(){

    }
    public int size() {
        return size;
    }

    public SerchTree(T val){
        root = new TreeNode(val);

    }
    public boolean isEmploy(){
        return root==null;
    }
    public void insert(T val){
        if(exist(val)){
            System.out.println("已存在");
            return;
        }else if(isEmploy()){
            root = new TreeNode<>(val);
        }else{
            insert(val,root);
        }
        size++;
    }
    public void delete(T val){
        root = delete(root,val);
        size--;
    }
    private TreeNode delete(TreeNode<T> root, T val) {
        if(root==null){
            return null;
        }
        if(root.val.compareTo(val)>0){
            root.left = delete(root.left,val);
        }else if(root.val.compareTo(val)<0){
            root.right = delete(root.right,val);
        }else{
            if(root.left!=null||root.right!=null){
                TreeNode<T> temp = root.left;
                while(temp.right!=null){
                    temp = temp.right;
                }
                root.val = temp.val;
                root.left = linked(root.left);
            }else if(root.left!=null){
                root = root.left;
            }else if(root.right!=null){
                root = root.right;
            }else {
                root = null;
            }
        }
        return root;
    }
    private TreeNode<T> linked(TreeNode treeNode){
        if(treeNode.right==null){
            return treeNode.left;
        }
        treeNode.right = linked(treeNode.right);
        return treeNode;
    }

    private void insert(T val,TreeNode<T> root){
        if(root.val.compareTo(val)<0){
            if(root.right==null){
                root.right = new TreeNode<>(val);
                return;
            }
            insert(val,root.right);
        }else {
            if(root.left==null){
                root.left = new TreeNode<>(val);
                return;
            }
            insert(val,root.left);
        }

    }
    private boolean exist(T val){
        return serch(val)!=null;
    }
    private TreeNode serch(T val){
        if(isEmploy()||val==root.val){
            return root;
        }
        return serch(root,val);
    }

    private TreeNode  serch(TreeNode<T> t,T val){
        if(t==null){
            return null;
        }
        if(t.val.compareTo(val)==0){
            return t;
        }
        if(t.val.compareTo(val)>0){
            return serch(t.left,val);
        }else {
            return serch(t.right,val);
        }
    }

    public static void main(String[] args){

        SerchTree<Integer> serchTree = new SerchTree<>();
        serchTree.insert(10);
        serchTree.insert(5);
        serchTree.insert(2);
        serchTree.insert(1);
        serchTree.insert(3);
        serchTree.insert(4);
        serchTree.insert(8);
        serchTree.insert(9);
        serchTree.insert(6);
        serchTree.insert(15);
        serchTree.insert(13);
        serchTree.insert(11);
        serchTree.delete(5);
        serchTree.insert(25);
        serchTree.insert(18);
        serchTree.insert(16);
        serchTree.insert(26);
        serchTree.delete(25);
        List<Integer> list = serchTree.toList("mid");
        for(int i:list){
            System.out.print(i+" ");
        }
        System.out.println();
        list = serchTree.toList("pre");
        for(int i:list){
            System.out.print(i+" ");
        }
        System.out.println();

        list = serchTree.toList("after");
        for(int i:list){
            System.out.print(i+" ");
        }
        System.out.println();

        list = serchTree.toList("levelOrder");
        for(int i:list){
            System.out.print(i+" ");
        }
        System.out.println();

        System.out.println(serchTree.depth());
        System.out.println(serchTree.size());
    }

}
//1 2 3 4 6 8 9 10 11 13 15 16 18 26
//        10 4 2 1 3 8 6 9 15 13 11 18 16 26
//        1 3 2 6 9 8 4 11 13 16 26 18 15 10
//        10 4 15 2 8 13 18 1 3 6 9 11 16 26
//        4
//        14
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个比较复杂的程序,需要一步步构建。我先给您提供一个框架,您可以根据需要进行修改和补充。 ```python class Node: def __init__(self, value): self.value = value self.left = None self.right = None class BinaryTree: def __init__(self, inorder, postorder): self.root = self.build_tree(inorder, postorder) def build_tree(self, inorder, postorder): if not inorder or not postorder: return None root = Node(postorder[-1]) root_index = inorder.index(root.value) root.left = self.build_tree(inorder[:root_index], postorder[:root_index]) root.right = self.build_tree(inorder[root_index+1:], postorder[root_index:-1]) return root def search(self, value): pass def height(self): pass def preorder(self, node): pass def inorder(self, node): pass def postorder(self, node): pass def levelorder(self, node): pass ``` 其,`Node` 类表示二点,包含一个值和左右子节点。`BinaryTree` 类表示二,包含根节点和各种方法。在构造函数,我们根据序序列和后序序列构建二。在 `build_tree` 方法,我们首先判断序列是否为空,如果为空则返回 `None`。否则,我们取后序序列的最后一个元素作为根节点,找到它在序序列的位置,然后将序序列分为左右两个部分,分别递归构建左右子。最终返回根节点。 接下来,我们需要补全其他方法的代码: ```python class BinaryTree: ... def search(self, value): def dfs(node): if not node: return None if node.value == value: return node left = dfs(node.left) if left: return left right = dfs(node.right) if right: return right return None return dfs(self.root) def height(self): def dfs(node): if not node: return 0 return max(dfs(node.left), dfs(node.right)) + 1 return dfs(self.root) def preorder(self, node): if not node: return [] return [node.value] + self.preorder(node.left) + self.preorder(node.right) def inorder(self, node): if not node: return [] return self.inorder(node.left) + [node.value] + self.inorder(node.right) def postorder(self, node): if not node: return [] return self.postorder(node.left) + self.postorder(node.right) + [node.value] def levelorder(self, node): if not node: return [] queue = [node] res = [] while queue: cur = queue.pop(0) res.append(cur.value) if cur.left: queue.append(cur.left) if cur.right: queue.append(cur.right) return res ``` 在 `search` 方法,我们采用深度优先搜索(DFS)的方式找指定值的点。在 `height` 方法,我们同样采用 DFS 的方式计算的高度。在 `preorder`、`inorder` 和 `postorder` 方法,分别实现了先序、序和后序遍。在 `levelorder` 方法,我们采用广度优先搜索(BFS)的方式实现层次。 最后,我们可以用以下方式测试程序: ```python inorder = ['D', 'B', 'E', 'A', 'F', 'C'] postorder = ['D', 'E', 'B', 'F', 'C', 'A'] tree = BinaryTree(inorder, postorder) assert tree.search('A').value == 'A' assert tree.search('X') == None assert tree.height() == 3 assert tree.preorder(tree.root) == ['A', 'B', 'D', 'E', 'C', 'F'] assert tree.inorder(tree.root) == ['D', 'B', 'E', 'A', 'F', 'C'] assert tree.postorder(tree.root) == ['D', 'E', 'B', 'F', 'C', 'A'] assert tree.levelorder(tree.root) == ['A', 'B', 'C', 'D', 'E', 'F'] ``` 这里我们构建了一个二,测试了各种方法的正确性。您可以根据需要修改测试用例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值