基本数据结构之二叉查找树

一、树的定义

线性数据结构: ArrayList、LinkedList及其组合HashMap。
非线性数据结构:树。
在这里插入图片描述
如上图,从数据结构进化的角度来看,树(tree) 的生成是 链表 进化而来。链(Linked) 每个节点最多只有一个 前驱节点 ,那么可以称这个 链 为 树(tree) 。

二、二叉查找树

1、定义:二叉树是每个节点最多只有两个子树的树。子树通常被称为左子树(Left subtree)和右子树(Right subtree)。如下图:
在这里插入图片描述

如下图,在二叉树基础上加上节点的大小关系就是二叉查找树:
在这里插入图片描述

2、实现
需要定义一个内部类Node,它包含两个分别指向左右节点的Node,一个用于排序的Key,以及该节点包含的值Value,还有一个记录该节点及所有子节点个数的值Number。

public class BinarySearchTreeSymbolTable<TKey, TValue> : SymbolTables<TKey, TValue> where TKey : IComparable<TKey>, IEquatable<TValue>
{
    private Node root;
    private class Node
    {
        public Node Left { get; set; }
        public Node Right { get; set; }
        public int Number { get; set; }
        public TKey Key { get; set; }
        public TValue Value { get; set; }

        public Node(TKey key, TValue value, int number)
        {
            this.Key = key;
            this.Value = value;
            this.Number = number;
        }
    }
...
}

3、 查询操作
查找操作和二分查找类似,将key和节点的key比较,如果小于,那么就在Left Node节点查找,如果大于,则在Right Node节点查找,如果相等,直接返回Value。

有两个实现方法:
①、递归方法:

public override TValue Get(TKey key)
{
    TValue result = default(TValue);
    Node node = root;
    while (node != null)
    {

        if (key.CompareTo(node.Key) > 0)
        {
            node = node.Right;
        }
        else if (key.CompareTo(node.Key) < 0)
        {
            node = node.Left;
        }
        else
        {
            result = node.Value;
            break;
        }
    }
    return result;
}

②、迭代方法

public TValue Get(TKey key)
{
    return GetValue(root, key);
}

private TValue GetValue(Node root, TKey key)
{
    if (root == null) return default(TValue);
    int cmp = key.CompareTo(root.Key);
    if (cmp > 0) return GetValue(root.Right, key);
    else if (cmp < 0) return GetValue(root.Left, key);
    else return root.Value;
}

最大最小值:
如下图,二叉树中,最左和最右节点即为最小值和最大值,迭代调用即可。
在这里插入图片描述
①、迭代方法:

public override TKey GetMax()
{
    TKey maxItem = default(TKey);
    Node s = root;
    while (s.Right != null)
    {
        s = s.Right;
    }
    maxItem = s.Key;
    return maxItem;
}

public override TKey GetMin()
{
    TKey minItem = default(TKey);
    Node s = root;
    while (s.Left != null)
    {
        s = s.Left;
    }
    minItem = s.Key;
    return minItem;
}

②、递归方法

public TKey GetMaxRecursive()
{
    return GetMaxRecursive(root);
}

private TKey GetMaxRecursive(Node root)
{
    if (root.Right == null) return root.Key;
    return GetMaxRecursive(root.Right);
}

public TKey GetMinRecursive()
{
    return GetMinRecursive(root);
}

private TKey GetMinRecursive(Node root)
{
    if (root.Left == null) return root.Key;
    return GetMinRecursive(root.Left);
}

4、 插入操作
插入和查找类似,首先查找有没有和key相同的,如果有,更新;如果没有找到,那么创建新的节点。并更新每个节点的Number值。

public override void Put(TKey key, TValue value)
{
    root = Put(root, key, value);
}

private Node Put(Node x, TKey key, TValue value)
{
    //如果节点为空,则创建新的节点,并返回
    //否则比较根据大小判断是左节点还是右节点,然后继续查找左子树还是右子树
    //同时更新节点的Number的值
    if (x == null) return new Node(key, value, 1);
    int cmp = key.CompareTo(x.Key);
    if (cmp < 0) x.Left = Put(x.Left, key, value);
    else if (cmp > 0) x.Right = Put(x.Right, key, value);
    else x.Value = value;
    x.Number = Size(x.Left) + Size(x.Right) + 1;
    return x;
}

private int Size(Node node)
{
    if (node == null) return 0;
    else return node.Number;
}

5、删除
①、删除最小值为例,我们首先找到最小值,及最左边左子树为空的节点,然后返回其右子树作为新的左子树(删除最大值同理)
在这里插入图片描述
代码实现:

public void DelMin()
{
    root = DelMin(root);
}

private Node DelMin(Node root)
{
    if (root.Left == null) return root.Right;
    root.Left = DelMin(root.Left);
    root.Number = Size(root.Left) + Size(root.Right) + 1;
    return root;
}

②、当删除的节点没有子节点,直接将该父节点指向该节点的link设置为null。
在这里插入图片描述

③、删除的节点只有一个子节点:将该子节点替换为要删除的节点即可
在这里插入图片描述

④、删除的节点有2个子节点:删除的节点t两个子节点,t具有右子节点,我们需要找到其右子节点中的最小节点,替换t节点的位置
- 保存待删除的节点到临时变量t
- 将t的右节点的最小节点min(t.right)保存到临时节点x
- 将x的右节点设置为deleteMin(t.right),该右节点是删除后,所有比x.key最大的节点。
- 将x的做节点设置为t的左节点。

如图所示:
在这里插入图片描述

代码实现:

public void Delete(TKey key)
{
    root =Delete(root, key);
        
}

private Node Delete(Node x, TKey key)
{
    int cmp = key.CompareTo(x.Key);
    if (cmp > 0) x.Right = Delete(x.Right, key);
    else if (cmp < 0) x.Left = Delete(x.Left, key);
    else
    {
        if (x.Left == null) return x.Right;
        else if (x.Right == null) return x.Left;
        else
        {
            Node t = x;
            x = GetMinNode(t.Right);
            x.Right = DelMin(t.Right);
            x.Left = t.Left;
        }
    }
    x.Number = Size(x.Left) + Size(x.Right) + 1;
    return x;
}

private Node GetMinNode(Node x)
{
    if (x.Left == null) return x;
    else return GetMinNode(x.Left); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值