二叉搜索树(Java)

1、二叉搜索树的来历:array查询方便,但添加删除元素比较麻烦(元素个数超过容量需要扩容,添加删除操作可能也要不停来回复制)。linked list方便添加元素,但是查询比较困难(只能从头一个个往下找)。因此发明了二叉搜索树这种数据结构,它是一种linked list结构,但集合了array和linked list的优点:方便查询;方便添加元素。
2、二叉搜索树的结构:就是一种linked list结构(这种class的filed里面至少包含一个reference能够指向未来的其他object地址),里面含2个reference(可以分别叫做left和right),一个可以比较大小的Key,一个值Value,以及整数N(表示该节点下面所连接的所有节点个数,包括该节点本身)。
3、二叉搜索树的特点:对于任意一个节点,它的Key值一定大于left指向节点的Key值,小于right指向节点的Key值。

二叉搜索树至少要包括添加,遍历,查询和删除这四个基本方法,我的设计思路分别如下:
1、添加。用递归法(递归实际保存了每层所有信息)。
方案一,void:每次带着以下信息(argument list)进入下一层:下一层的reference(往哪儿去),这一层的reference,左连接还是右连接,Key值,Value值。在下一层的任务:检查带入的Key值和已有Key值。若覆写(Key值相等),就更新Value值,然后原路返回顶层(回去的路上顺带更新一下N值);若不覆写(Key值没对上号),继续带上新信息往下走,最终将进入一片空白区域,在此区域要完成Key值,Value值的录入,再根据上一层的reference,把本层的reference连接到其左侧或右侧,然后原路返回顶层(返回的路上顺便更新一下N值)。
方案二,带return:进入下一层时,不需要携带那么多信息,只带上:下一层的reference(往哪儿去),Key值和Value值。因为反正还要原路返回,只要返回的时候带上下一层的reference就可以。因此在每一层的任务是:检查带入的Key值和已有Key值是否相等。若相等,执行覆写操作,但注意原路返回的同时要记下下一层的reference,回到上一层把他关联给其left或right,并更新N值(尽管覆写操作这样返回没什么意义)。若不等,继续带上新信息往下走,最终将到达一片空白之地,在这里完成Key值和Value的录入,原路返回之前,记下本层reference,然后返回给上一层的left或right,顺便更新N值。
2、遍历(但大小顺序)。仍然用递归法。
方案一,void:遍历跟查找类似,不需要跟添加删除那样改变原有数据结构,因此所携带的信息非常少,只有一个root。假设从小到大遍历。我们首先一定会要找到最小值,方法是从root开始,一路左走。最终走到了最小值的左边,也就是null。这时需要停下来,返回上一层(最小值所在层),然后打印上一层信息。完成以后,我们要找比最小值稍大一点的数,也就是右侧最小值,若不为空,继续一路左走深入下去,若右侧为空,那么本层也结束了,应返回上一层,打印信息,再找上一层的右侧最小值...
方案二,带return:跟一差不多,只不过每层都要返回reference再关联第二遍。优点画蛇添足。

添加和遍历具体如下:
public class BST<Key extends Comparable<Key>, Value>
{
    private Node root;

    public Node getRoot() { return root; }

    private class Node
    {
        Node left, right;
        int N;
        Key key;
        Value val;
        Node(Key key, Value val)
        {
            this.key = key;
            this.val = val;
            N = 1;
        }
    }

    public int size() { return size(root); }

    private int size(Node x)
    {
        if(x == null) return 0;
        else return x.N;
    }

    public void addElement(Key key, Value val) { root = addElement(key, val, root); }

    private Node addElement(Key key, Value val, Node x)
    {
        if(x == null) return new Node(key, val);
        int cmp = key.compareTo(x.key);
        if(cmp > 0) x.right = addElement(key, val, x.right);
        else if(cmp < 0) x.left = addElement(key, val, x.left);
        else x.val = val;
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }

    public void add(Key key, Value val) { add(key, val, root, null, 2); }

    private void add(Key key, Value val, Node current, Node previous, int i)
    {
        if(current == null)
        {
            if(i == 0) previous.left = new Node(key, val);
            else if(i == 1) previous.right = new Node(key, val);
            else root = new Node(key, val);
        }
        else
        {
            int cmp = key.compareTo(current.key);
            if(cmp < 0) add(key, val, current.left, current, 0);
            else if(cmp > 0) add(key, val, current.right, current, 1);
            else current.val = val;
            current.N = size(current.left) + size(current.right) + 1;
        }
    }

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

    private Node iterate(Node x)
    {
        if(x != null)
        {
            x.left = iterate(x.left);
            System.out.println(x.key + ": " + x.val);
            x.right = iterate(x.right);
        }
        return x;
    }

    public void iterate2() { iterate2(root); }

    private void iterate2(Node x)
    {
        if(x == null) return;
        else
        {
            iterate2(x.right);
            System.out.println(x.key + ": " + x.val);
            iterate2(x.left);
        }
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值