B树的java源码实现

本文介绍了如何根据《算法导论》第二版第十八章的内容,利用Java实现一颗简单的B树。作者分享了B树的实现过程,旨在促进讨论和交流,减少磁盘I/O操作。
摘要由CSDN通过智能技术生成

B树是为磁盘或其他直接存取辅助存储设置而设计的一种平衡查找树。其能够有效降低磁盘I/O操作次数。许多数据库系统使用B树或B树的变形来储存信息。清明节这几天闲来无事,参考《算法导论》第二版第十八章的思想使用java语言实现了一颗简单的B树,在此跟大家分享下,就当是抛砖引玉,欢迎大家跟我讨论。

package com.discover;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Random;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 一颗B树的简单实现。
 * <p/>
 * 其实现原理参考《算法导论》第二版第十八章。
 * <p/>
 * 如果大家想读懂这些源代码,不妨先看看上述章节。
 * <p/>
 * TODO B树如何存储在文件系统中,大家不妨想想
 * 
 * @author WangPing 欢迎转载,转载请标明原文地址
 *
 * @param <K> - 键类型
 * @param <V> - 值类型
 */
public class BTree<K, V>
{
	private static Log logger = LogFactory.getLog(BTree.class);
	
	/**
	 * B树节点中的键值对。
	 * <p/> 
	 * B树的节点中存储的是键值对。
	 * 通过键访问值。
	 *
	 * @param <K> - 键类型
	 * @param <V> - 值类型
	 */
	private static class Entry<K, V>
	{
		private K key;
		private V value;
		
		public Entry(K k, V v)
		{
			this.key = k;
			this.value = v;
		}
		
		public K getKey()
		{
			return key;
		}
		
		public V getValue()
		{
			return value;
		}
		
		public void setValue(V value)
		{
			this.value = value;
		}
		
		@Override
		public String toString()
		{
			return key + ":" + value;
		}
	}
	
	/**
	 * 在B树节点中搜索给定键值的返回结果。
	 * <p/> 
	 * 该结果有两部分组成。第一部分表示此次查找是否成功,
	 * 如果查找成功,第二部分表示给定键值在B树节点中的位置,
	 * 如果查找失败,第二部分表示给定键值应该插入的位置。
	 */
	private static class SearchResult<V>
	{
		private boolean exist;
		private int index;
		private V value;
		
		public SearchResult(boolean exist, int index)
		{
			this.exist = exist;
			this.index = index;
		}
		
		public SearchResult(boolean exist, int index, V value)
		{
			this(exist, index);
			this.value = value;
		}
		
		public boolean isExist()
		{
			return exist;
		}
		
		public int getIndex()
		{
			return index;
		}
		
		public V getValue() 
		{
			return value;
		}
	}
	
	/**
	 * B树中的节点。
	 * 
	 * TODO 需要考虑并发情况下的存取。
	 */
	private static class BTreeNode<K, V>
	{
		/** 节点的项,按键非降序存放 */
		private List<Entry<K,V>> entrys;
		/** 内节点的子节点 */
		private List<BTreeNode<K, V>> children;
		/** 是否为叶子节点 */
		private boolean leaf;
		/** 键的比较函数对象 */
		private Comparator<K> kComparator;
		
		private BTreeNode()
		{
			entrys = new ArrayList<Entry<K, V>>();
			children = new ArrayList<BTreeNode<K, V>>();
			leaf = false;
		}
		
		public BTreeNode(Comparator<K> kComparator)
		{
			this();
			this.kComparator = kComparator;
		}
		
		public boolean isLeaf()
		{
			return leaf;
		}
		
		public void setLeaf(boolean leaf)
		{
			this.leaf = leaf;
		}
		
		/**
		 * 返回项的个数。如果是非叶子节点,根据B树的定义,
		 * 该节点的子节点个数为({@link #size()} + 1)。
		 * 
		 * @return 关键字的个数
		 */
		public int size()
		{
			return entrys.size();
		}
		
		@SuppressWarnings("unchecked")
		int compare(K key1, K key2)
		{
			return kComparator == null ? ((Comparable<K>)key1).compareTo(key2) : kComparator.compare(key1, key2);
		}
		
		/**
		 * 在节点中查找给定的键。
		 * 如果节点中存在给定的键,则返回一个<code>SearchResult</code>,
		 * 标识此次查找成功,给定的键在节点中的索引和给定的键关联的值;
		 * 如果不存在,则返回<code>SearchResult</code>,
		 * 标识此次查找失败,给定的键应该插入的位置,该键的关联值为null。
		 * <p/>
		 * 如果查找失败,返回结果中的索引域为[0, {@link #size()}];
		 * 如果查找成功,返回结果中的索引域为[0, {@link #size()} - 1]
		 * <p/>
		 * 这是一个二分查找算法,可以保证时间复杂度为O(log(t))。
		 * 
		 * @param key - 给定的键值
		 * @return - 查找结果
		 */
		public SearchResult<V> searchKey(K key)
		{
			int low = 0;
			int high = entrys.size() - 1;
			int mid = 0;
			while(low <= high)
			{
				mid = (low + high) / 2; // 先这么写吧,BTree实现中,l+h不可能溢出
				Entry<K, V> entry = entrys.get(mid);
				if(compare(entry.getKey(), key) == 0) // entrys.get(mid).getKey() == key
					break;
				else if(compare(entry.getKey(), key) > 0) // entrys.get(mid).getKey() > key
					high = mid - 1;
				else // entry.get(mid).getKey() < key
					low = mid + 1;
			}
			boolean result = false;
			int index = 0;
			V value = null;
			if(low &l
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值