自己动手实现java数据结构(六)二叉搜索树(4)
当返回的相对位置为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站长网) |