之前看了刘新宇大大的《算法新解》有了点收获,闲来无事,便写了一个二叉搜索树实现的Map类。

java的Map接口有很多不想要的方法,自己定义了一个

 public interface IMap<K, V> {
V get(K k); void put(K k, V v); V remove(K k);
}

具体实现:

 public class BSTree<K, V> implements IMap<K, V> {
Entry<K, V> head = null; @Override
public V get(K k) {
return get(head, k);
} private V get(Entry<K, V> node, K k) {
if (node == null) {
return null;
}
int compare = compare(node.key, k);
if (compare == 0) {
return node.value;
} else if (compare > 1) {
return get(node.right, k);
} else {
return get(node.left, k);
}
} @Override
public void put(K k, V v) {
//1.head is null
if (head == null) {
head = new Entry<>(k, v, null);
}
//2.head is not null
else {
put(head, k, v);
}
} private void put(Entry<K, V> node, K k, V v) {
int compare = compare(node.key, k);
if (compare == 0) {
node.value = v;
} else if (compare > 1) {
if (node.right == null) {
node.right = new Entry<>(k, null, node);
}
put(node.right, k, v);
} else {
if (node.left == null) {
node.left = new Entry<>(k, null, node);
}
put(node.left, k, v);
}
} private int compare(K key, K k) {
return ((Comparable) key).compareTo(k);
} @Override
public V remove(K k) {
return remove(head, k);
} private V remove(Entry<K, V> node, K k) {
if (node == null) {
return null;
}
int compare = compare(node.key, k);
if (compare == 0) {
//1.no child
if (node.left == null && node.right == null) {
if (node.parent == null)
head = null;
else if (node == node.parent.left) {
node.parent.left = null;
} else {
node.parent.right = null;
}
return node.value;
}
//2.has right child
else if (node.right != null) {
V oldValue = node.value;
Entry<K, V> newNode = findMin(node.right);
node.key=newNode.key;
node.value = newNode.value;
newNode.parent.right = null;
return oldValue;
}
//3.has no right child,has left child
else{
V oldValue = node.value;
Entry<K, V> newNode = findMax(node.left);
node.key=newNode.key;
node.value = newNode.value;
newNode.parent.left= null;
return oldValue;
} } else if (compare > 0) {
return remove(node.right, k);
} else {
return remove(node.left, k);
}
} private Entry<K, V> findMax(Entry<K, V> left) {
if (left.right == null) {
return left;
}else{
return findMax(left.right);
}
} private Entry<K, V> findMin(Entry<K, V> right) {
if (right.left == null) {
return right;
}else {
return findMin(right.left);
}
} class Entry<K, V> {
K key;
V value;
Entry<K, V> left;
Entry<K, V> right;
Entry<K, V> parent; private Entry(K key, V value, Entry<K, V> parent) {
this.key = key;
this.value = value;
left = null;
right = null;
this.parent = parent;
}
} }

测试的类:

 public class BSTreeTest {
private static int write_num = 100_0000;
private static int read_num = 100_0000; public static void main(String[] args) {
// IMap<String,Integer> map = new BSTree();
// Map<String, Integer> map = new TreeMap<>();
// Map<String, Integer> map = new HashMap<>();
Map<String, Integer> map = new LinkedHashMap<>();
long start = System.nanoTime();
for (int i = 0; i < write_num; i++) {
map.put("" + i, i);
}
for (int i = 0; i < read_num; i++) {
Integer s = map.get(i + "");
assert s.equals(i);
}
for (int i = 0; i < read_num / 2; i++) {
map.remove(i + "");
}
for (int i = 0; i < read_num / 2; i++) {
Integer s = map.get(i + "");
assert s == null;
}
for (int i = read_num / 2; i < read_num / i++; i++) {
Integer s = map.get(i + "");
assert s.equals(i);
}
System.out.println("map cost:" + (System.nanoTime() - start));
}
}

在各自只运行一次的情况下测试数据如下:

map cost:1125174394 //myMap
map cost:812963047 //TreeMap
map cost:475993738 //HashMap
map cost:475993738 //LinkedHashMap

由于二叉搜索树没有自平衡机制,搜索的时间在O(n*n)与O(lgn)之间摇摆,因此对比java用红黑树实现的TreeMap时间O(lgn)要多上很多。

使用二叉搜索树实现一个简单的Map的更多相关文章

  1. [CareerCup] 4.6 Find Next Node in a BST 寻找二叉搜索树中下一个节点

    4.6 Write an algorithm to find the'next'node (i.e., in-order successor) of a given node in a binary ...

  2. LeetCode-450 二叉搜索树删除一个节点

    二叉搜索树 建树 删除节点,三种情况,递归处理.左右子树都存在,两种方法,一种找到左子树最大节点,赋值后递归删除.找右子树最小同理 class Solution { public: TreeNode* ...

  3. LeetCode(98): 验证二叉搜索树

    Medium! 题目描述: 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右 ...

  4. 二叉搜索树-php实现 插入删除查找等操作

    二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的 ...

  5. 「面试高频」二叉搜索树&双指针&贪心 算法题指北

    本文将覆盖 「字符串处理」 + 「动态规划」 方面的面试算法题,文中我将给出: 面试中的题目 解题的思路 特定问题的技巧和注意事项 考察的知识点及其概念 详细的代码和解析 开始之前,我们先看下会有哪些 ...

  6. Java实现二叉搜索树的插入、删除

    前置知识 二叉树的结构 public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() { } TreeNode( ...

  7. lintcode: 把排序数组转换为高度最小的二叉搜索树

    题目: 把排序数组转换为高度最小的二叉搜索树 给一个排序数组(从小到大),将其转换为一棵高度最小的排序二叉树. 样例 给出数组 [1,2,3,4,5,6,7], 返回 4 / \ 2 6 / \ / ...

  8. [Data Structure] 二叉搜索树(Binary Search Tree) - 笔记

    1. 二叉搜索树,可以用作字典,或者优先队列. 2. 根节点 root 是树结构里面唯一一个其父节点为空的节点. 3. 二叉树搜索树的属性: 假设 x 是二叉搜索树的一个节点.如果 y 是 x 左子树 ...

  9. LeetCode - 验证二叉搜索树

    给定一个二叉树,判断其是否是一个有效的二叉搜索树. 一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是二叉搜索树. ...

随机推荐

  1. 成为一名自由UX设计师--你“够格”吗?

    和传统的朝九晚五,三点一线的生活状态相比,现在互联网时代下的年轻人更崇尚对自由的追求.“可任意支配时间”.“工作场所自由”和“收入高”是人们选择成为自由职业者的主要原因.特别是IT行业中的设计师群体, ...

  2. 静态HTML服务器

    主要代码 #pragma once#include "pre.h"#include <thread> NAMESPACE(DEF) class Socket {publ ...

  3. 如何用Python实现常见机器学习算法-4

    四.SVM支持向量机 1.代价函数 在逻辑回归中,我们的代价为: 其中: 如图所示,如果y=1,cost代价函数如图所示 我们想让,即z>>0,这样的话cost代价函数才会趋于最小(这正是 ...

  4. spark yarn 集群提交kafka代码

    配置好hadoop的环境,具体根据http://blog.csdn.net/u010638969/article/details/51283216博客所写的进行配置. 运行start-dfs.sh启动 ...

  5. jQuery自定义动画

    $(function(){ $(".btn1").click(function(){ $(','opacity':'toggle'}); }); $(".btn2&quo ...

  6. 整理悬浮在列表中a元素时改变a元素上下边框颜色的问题。

    整理一下当悬浮在a元素上时a的上下边颜色改变,并且里面的内容不会移动,下面是PSD图效果区域: 刚开始我先给A元素加了上下边框和颜色,利用a:hover改变a元素上下的边框颜色,但是第一个a元素的下边 ...

  7. CSS实现图片阴影效果

    <title>无标题文档</title> <style type="text/css"> /*方法一:使用一个GIF文件的方法*/ .gifsh ...

  8. OpengGL中图形绘制先后问题

    OpengGL中图形绘制先后问题 在opengl中,场景绘制总有个先后的顺序,也有个程序先后的问题,图形程序在前在后,对最终的图形的影响如何? (1)设置图中的点(蓝色)与线条(浅蓝)z分量都是0,如 ...

  9. Android-openFileInput openFileOutput

    Android设计了一套可以操作自身APP目录文件对API openFileInput openFileOutput,读取只需传入文件名,写入需要传入文件名 与 权限模式 界面: 布局代码: < ...

  10. Provider 模式

    Provider 模式:为一个API进行定义和实现的分离. 常见场景:DBPrider切换,第3方集成API切换 以发邮件为例: Email Provider Config: public abstr ...