二叉树(链表实现)--增、删、改、查

二叉树(链表实现)

1.1 树的基本定义

​ 树是我们计算机中非常重要的一种数据结构,同时使用树这种数据结构,可以描述现实生活中的很多事物,例如家谱、单位的组织架构、等等。

​ 树是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aFMHDifj-1627167495963)(E:\personal\Node\数据结构与算法\笔记\assets\image14.png)]

树具有以下特点:

  1. 每个结点有零个或多个子结点;
  2. 没有父结点的结点为根结点;
  3. 每一个非根结点只有一个父结点;
  4. 每个结点及其后代结点整体上可以看做是一棵树,称为当前结点的父结点的一个子树;
1.2 树的相关术语

结点的度:

一个结点含有的子树的个数称为该结点的度;

叶结点:

度为0的结点称为叶结点,也可以叫做终端结点

分支结点:

度不为0的结点称为分支结点,也可以叫做非终端结点

结点的层次:

从根结点开始,根结点的层次为1,根的直接后继层次为2,以此类推

结点的层序编号:

将树中的结点,按照从上层到下层,同层从左到右的次序排成一个线性序列,把他们编成连续的自然数。

树的度:

树中所有结点的度的最大值

树的高度(深度):

树中结点的最大层次

森林:

m(m>=0)个互不相交的树的集合,将一颗非空树的根结点删去,树就变成一个森林;给森林增加一个统一的根结点,森林就变成一棵树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZjTP85Ya-1627167495965)(E:\personal\Node\数据结构与算法\笔记\assets\image15.png)]

孩子结点:

一个结点的直接后继结点称为该结点的孩子结点

双亲结点(父结点):

一个结点的直接前驱称为该结点的双亲结点

兄弟结点:

同一双亲结点的孩子结点间互称兄弟结点

1.3 二叉树的基本定义

​ 二叉树就是度不超过2的树(每个结点最多有两个子结点)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2PxHBOPY-1627167495967)(E:\personal\Node\数据结构与算法\笔记\assets\image16.png)]

满二叉树:

一个二叉树,如果每一个层的结点树都达到最大值,则这个二叉树就是满二叉树。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n1hFdYzz-1627167495968)(E:\personal\Node\数据结构与算法\笔记\assets\image17.png)]

描述公式
每一层结点的个数上传(img-9KTadB5x-1627167495968)(E:\personal\Node\数据结构与算法\笔记\assets\image19.png)]k为层数

完全二叉树:

叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kmAyhdef-1627167495969)(E:\personal\Node\数据结构与算法\笔记\assets\image18.png)]

1.4 二叉查找树的创建

结点类API设计:

类名Node<Key,Value>
构造方法Node(Key key, Value value, Node left, Node right):创建Node对象
成员变量1.public Node left:记录左子结点
2.public Node right:记录右子结点
3.public Key key:存储键
4.public Value value:存储值

二叉查找树API设计:

类名BinaryTree<Key extends Comparable,Value>
构造方法BinaryTree():创建BinaryTree对象
成员变量1.private Node root:记录根结点
2.private int N:记录树中元素的个数
成员方法1. public void put(Key key,Value value):向树中插入一个键值对
2.private Node put(Node x, Key key, Value val):给指定树x上,添加一个键值对,并返回添加后的新树
3.public Value get(Key key):根据key,从树中找出对应的值
4.private Value get(Node x, Key key):从指定的树x中,找出key对应的值
5.public void delete(Key key):根据key,删除树中对应的键值对
6.private Node delete(Node x, Key key):删除指定树x上的键为key的键值对,并返回删除后的新树
7.public int size():获取树中元素的个数
8.public Key min():找出树中最小的键
9.private Node min(Node x):找出指定树x中,最小键所在的结点
10.public Key max():找出树中最大的键
11.public Node max(Node x):找出指定树x中,最大键所在的结点

二叉查找树实现

插入方法put实现思想:

1.如果当前树中没有任何一个结点,则直接把新结点当做根结点使用

2.如果当前树不为空,则从根结点开始:

2.1如果新结点的key小于当前结点的key,则继续找当前结点的左子结点;

2.2如果新结点的key大于当前结点的key,则继续找当前结点的右子结点;

2.3如果新结点的key等于当前结点的key,则树中已经存在这样的结点,替换该结点的value值即可。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NgeKiouA-1627167495970)(E:\personal\Node\数据结构与算法\笔记\assets\image20.png)]

查询方法get实现思想:

从根节点开始:

1.如果要查询的key小于当前结点的key,则继续找当前结点的左子结点;

2.如果要查询的key大于当前结点的key,则继续找当前结点的右子结点;

3.如果要查询的key等于当前结点的key,则树中返回当前结点的value。

删除方法delete实现思想:

1.找到被删除结点;

2.找到被删除结点右子树中的最小结点minNode

3.删除右子树中的最小结点

4.让被删除结点的左子树称为最小结点minNode的左子树,让被删除结点的右子树称为最小结点minNode的右子树

5.让被删除结点的父节点指向最小结点minNode

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WlIUIz2R-1627167495970)(E:\personal\Node\数据结构与算法\笔记\assets\image21.png)]

代码:

/**
 * 二叉树
 */
public class BinaryTree<Key extends Comparable<Key>, Value> {
    // 记录根结点
    private Node root;
    // 记录树中元素的个数
    private int N;

    public BinaryTree() {
    }

    // 获取树中的元素个数
    public int size() {
        return N;
    }

    // 向树中添加元素key-value
    public void put(Key key, Value value) {
        root = put(root, key, value);
    }

    // 向指定的树x中添加key-value,并返回添加元素后新的树
    private Node put(Node x, Key key, Value value) {
        // 如果x结点为空,则直接创建新结点存储数据并返回
        if (x == null) {
            // 元素个数+1
            N++;
            return new Node(key, value, null, null);
        }
        // 如果x结点不为空,则将x.key与传入的key进行比较,寻找插入点
        // 如果(key>x.key),则继续寻找当前结点的右子结点
        if (key.compareTo(x.key) > 0) {
            x.right = put(x.right, key, value);
        }
        // 如果(key<x.key),则继续寻找当前结点的左子结点
        if (key.compareTo(x.key) < 0) {
            x.left = put(x.left, key, value);
        }
        // 如果(key=x.key),则替换当前结点的value值
        if (key.compareTo(x.key) == 0) {
            x.value = value;
        }
        return x;
    }

    // 查询树中指定key对应的value
    public Value get(Key key) {
        return get(root, key);
    }

    // 从指定的树x中,查找key对应的值
    private Value get(Node x, Key key) {
        // x树为null
        if (x == null)
            return null;
        // x树不为null
        // 如果(key<x.key),递归查询当前结点的左子树
        if (key.compareTo(x.key) < 0) {
            return get(x.left, key);
        }
        // 如果(key>x.key),递归查询当前结点的右子树
        if (key.compareTo(x.key) > 0) {
            return get(x.right, key);
        }
        // 如果(key=x.key),返回当前结点的value值
        if (key.compareTo(x.key) == 0) {
            return x.value;
        }
        return null;
    }

    // 删除树中key对应的value
    public void delete(Key key) {
        delete(root, key);
    }

    // 删除指定树x中的key对应的value,并返回删除后的新树
    private Node delete(Node x, Key key) {
        // 如果x结点为空,直接返回空置
        if (x == null) {
            return null;
        }
        // 如果x结点不为空,则比较key值,找到要删除的结点
        // 如果(key>x.key),查找当前结点的右子树
        if (key.compareTo(x.key) > 0) {
            x.right = delete(x.right, key);
        }
        // 如果(key<x.key),查找当前结点的左子树
        if (key.compareTo(x.key) < 0) {
            x.left = delete(x.left, key);
        }
        // 如果(key=x.key),找到要删除的结点,进行删除
        if (key.compareTo(x.key) == 0) {
            // 要找到x结点的右子树中最小的结点,替换x结点
            // 如果x结点的右子树为空,则直接返回x的左子树
            if (x.right == null) {
                // 元素个数-1
                N--;
                return x.left;
            }
            // 如果x结点的左子树为空,则直接返回x的右子树
            if (x.left == null) {
                // 元素个数-1
                N--;
                return x.right;
            }
            // 如果x的左右子树都存在,则找到x结点右子树中的最小结点,并替换x结点
            Node minNode = x.right;
            while (minNode.left != null) {
                minNode = minNode.left;
            }
            // 删除树中minNode结点
            Node n = x.right;
            while (n.left != null) {
                if (n.left == minNode) {
                    n.left = null;
                }
                n = n.left;
            }
            // 用minNode替换x结点,让minNode的左右子树成为x的左右子树
            minNode.left = x.left;
            minNode.right = x.right;
            // 元素个数-1
            N--;
            // 返回删除后更换子树()
            x = minNode;
        }
        return x;
    }

    // 查找树中最小的键
    public Key min() {
        return min(root).key;
    }

    // 查找指定树中最小的键所在的结点
    private Node min(Node x) {
        // 判断x结点是否还有左子树,有继续向左遍历,没有则就是最小的结点
        if (x.left != null) {
            return min(x.left);
        } else {
            return x;
        }
    }

    // 查找树中最大的键
    public Key max() {
        return max(root).key;
    }

    // 查找树中最大键所在的结点
    private Node max(Node x) {
        // 判断x结点是否还有右子树,有继续向左遍历,没有则就是最大的结点
        if (x.right != null) {
            return max(x.right);
        } else {
            return x;
        }
    }

    // 结点类
    private class Node {
        // 存储键
        private Key key;
        // 存储值
        private Value value;
        // 记录左子结点
        private Node left;
        // 记录右子结点
        private Node right;

        public Node(Key key, Value value, Node left, Node right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农村小白i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值