设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 手机 数据 公司
当前位置: 首页 > 服务器 > 安全 > 正文

自己动手实现java数据结构(六)二叉搜索树(4)

发布时间:2021-04-01 04:47 所属栏目:53 来源:网络整理
导读:当返回的相对位置为Current时,代表找到了目标节点,直接返回value;反之代表目标节点不存在,返回null。 V get(K key) { targetEntryNode.target.value; } } 3.7?二叉搜索树其它接口实现 containsKey(K key) { ret

  当返回的相对位置为Current时,代表找到了目标节点,直接返回value;反之代表目标节点不存在,返回null。

 V get(K key) {
         targetEntryNode.target.value;
        }
    }

3.7?二叉搜索树其它接口实现

 containsKey(K key) {
        return (get(key) != );
    }

    @Override
     containsValue(V value) {
        :::寻找到第一个节点
        EntryNode<K,V> entryNode = getFirstNode();

        :::从第一个节点开始,遍历整颗二叉搜索树
        while(entryNode != if(Objects.equals(entryNode.value,value)){
                :::当前节点value匹配,返回true
                true:::指向下一个直接后继节点
                entryNode = getSuccessor(entryNode);
            }
        }

        :::遍历整颗树之后,还未匹配,返回false
        false;
    }

    @Override
     size() {
        .size;
    }

    @Override
     isEmpty() {
        return (this.size == 0 clear() {
        this.size = 0;
         String toString(){
        Iterator<Map.EntryNode<K,V>> iterator = .iterator();

        :::空容器
        if(!iterator.hasNext()){
            return "[]":::容器起始使用"["
        StringBuilder s = new StringBuilder("[");

        :::反复迭代
        while(:::获得迭代的当前元素
            Map.EntryNode<K,V> data = iterator.next();

            :::判断当前元素是否是最后一个元素
            iterator.hasNext()){
                :::是最后一个元素,用"]"收尾
                s.append(data).append("]");
                :::返回 拼接完毕的字符串
                 s.toString();
            }:::不是最后一个元素
                :::使用","分割,拼接到后面
                s.append(data).append(",");
            }
        }
    }

    @Override
    public Iterator<Map.EntryNode<K,1)"> iterator() {
        new Itr();
    }

4.二叉搜索树迭代器

  1. 二叉搜索树从最左节点开始,以中序遍历的方式遍历整颗树

  2. 在迭代器初始化时,迭代器指向最小的节点(也就是最左节点)

  3. 迭代器迭代时,下一个节点总是指向当前节点的直接后继

  
     * 二叉搜索树 迭代器实现
     * class Itr implements Iterator<Map.EntryNode<K,1)">
         * 当前迭代节点
         *  currentNode;

        
         * 下一个节点
         *  nextNode;

         Itr() {
            :::初始化时,nextNode指向第一个节点
            this.nextNode = TreeMap..getFirstNode();
        }

        @Override
         hasNext() {
            this.nextNode != );
        }

        @Override
        public Map.EntryNode<K,1)"> next() {
            this.currentNode = .nextNode;

            this.getSuccessor(.nextNode);

            .currentNode;
        }

        @Override
         remove() {
            this.currentNode == new IteratorStateErrorException("迭代器状态异常: 可能在一次迭代中进行了多次remove操作");
            }

            :::判断当前被删除的节点是否同时存在左右孩子
            this.currentNode.left != null && this.currentNode.right != 
                    同时存在左右孩子的节点删除时当前节点会和直接后继(nextNode)进行交换
                    因此nextNode指向当前节点
                 */
                this.nextNode = .currentNode;
            }
            :::删除当前节点
            TreeMap.this.deleteEntryNode(.currentNode);

            :::currentNode设置为null,防止反复调用remove方法
            ;
        }
    }

5.二叉搜索树性能

5.1 空间效率

  二叉搜索树的内部节点除了key,value的引用,同时还维护着双亲,左右孩子节点的引用(不一定存在),因此其空间效率比链表稍差,更是不如向量结构紧凑。但是这一点点空间效率的损失,带来的是二叉搜索树全面而优异的增删改查效率。

5.2 时间效率

  二叉搜索树的插入,删除依赖于查询接口,而查询接口是以二分查找的方式实现的。在理想状态下(平衡的),二叉搜索树的增删改查接口的效率为(O(logN)),N为当前二叉搜索树存储的元素总数;也可以说,二叉搜索树增删改查接口的效率正比于二叉搜索树的高度。

6.二叉搜索树总结

6.1 当前版本缺陷:

  至此,我们实现了一个最基础的二叉搜索树,但还存在一个致命缺陷:

  二叉搜索树在插入数据时,以二分查找的方式确定插入的位置。但是当插入数据的数据不够随机时,会降低二叉搜索树的查询效率。举个极端例子,当按照顺序插入1到10000的元素以从小到大顺序插入,二叉搜索树将退化为一个一维的链表(极端不平衡),查询效率从O(logN)急剧降低为O(n)。

  我们希望在插入,删除元素时,通过及时的调整二叉搜索树结构,用一系列等价变换的操作,使二叉搜索树始终保持一个适度平衡的状态。我们称这样的二叉搜索树为平衡二叉搜索树(Balanced?Binary?Search?Tree),常见的平衡二叉搜索树有AVL树、红黑树等。

  只有平衡二叉搜索树才能始终保证始终高效的查询效率(O(logN)),而不会因为极端数据集合的插入,造成效率的大幅降低。

6.2 完整代码

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读