B+树JAVA实现

B+树是一种多路平衡查找树,是对B树(B-Tree)的扩展.
是一个n叉排序树,每个节点通常有多个孩子,一棵B+树包含根节点、内部节点和叶子节点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点。
B+ 树通常用于数据库和操作系统的文件系统中。NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系统都在使用B+树作为元数据索引。B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入。
B+树是B-树的一种变体,性能比B-树更好。
B+树除了具有B-树的特征外,也具有一些新的特性

一个m阶的B+树具有如下几个特征:
1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。
基于这几点以及网上B+树代码实现,实现了B+树:

package com.lin.tree;

public class BPlusTree> {

	private Integer bTreeOrder;

	private Integer maxNumber;

	private Node root;

	private LeafNode left;

	public BPlusTree() {
		this(3);
	}

	public BPlusTree(Integer bTreeOrder) {
		this.bTreeOrder = bTreeOrder;
		this.maxNumber = bTreeOrder + 1;
		this.root = new LeafNode();
		this.left = null;
	}

	public T find(V key) {
		T t = this.root.find(key);
		if (t == null) {
			System.out.println("找不到:" + key);
		}
		return t;
	}

	public void insert(T value, V key) {
		if (key == null)
			return;
		Node t = this.root.insert(value, key);
		if (t != null)
			this.root = t;
		this.left = (LeafNode) this.root.refreshLeft();
	}

	abstract class Node> {

		protected Node parent;
		protected Node[] childs;

		protected Integer number;

		protected Object[] keys;

		public Node() {
			this.keys = new Object[maxNumber];
			this.childs = new Node[maxNumber];
			this.number = 0;
			this.parent = null;
		}

		abstract T find(V key);

		abstract Node insert(T value, V key);

		abstract LeafNode refreshLeft();

	}

	class BPlusNode> extends Node {

		public BPlusNode() {
			super();
		}

		@Override
		T find(V key) {
			int i = 0;
			while (i < this.number) {
				if (key.compareTo((V) this.keys[i]) <= 0)
					break;
				i++;

			}
			if (this.number == i)
				return null;

			return this.childs[i].find(key);
		}

		@Override
		Node insert(T value, V key) {
			int i = 0;
			while (i < this.number) {
				if (key.compareTo((V) this.keys[i]) < 0)
					break;
				i++;
			}
			if (key.compareTo((V) this.keys[this.number - 1]) > 0)
				i--;

			return this.childs[i].insert(value, key);
		}

		@Override
		LeafNode refreshLeft() {
			return this.childs[0].refreshLeft();
		}

		Node insertNode(Node node1, Node node2, V key) {

			V oldKey = null;
			if (this.number > 0)
				oldKey = (V) this.keys[this.number - 1];

			if (key == null || this.number <= 0) {
				this.keys[0] = node1.keys[node1.number - 1];
				this.keys[1] = node2.keys[node2.number - 1];
				this.childs[0] = node1;
				this.childs[1] = node2;
				this.number += 2;
				return this;

			}
			int i = 0;
			while (key.compareTo((V) this.keys[i]) != 0) {
				i++;
			}
			this.keys[i] = node1.keys[node1.number - 1];
			this.childs[i] = node1;
			Object tempKeys[] = new Object[maxNumber];
			Object tempChilds[] = new Node[maxNumber];

			System.arraycopy(this.keys, 0, tempKeys, 0, i + 1);
			System.arraycopy(this.childs, 0, tempChilds, 0, i + 1);
			System.arraycopy(this.keys, i + 1, tempKeys, 0, this.number - i - 1);
			System.arraycopy(this.childs, i + 1, tempChilds, 0, this.number - i - 1);
			;

			tempKeys[i + 1] = node2.keys[node2.number - 1];
			tempChilds[i + 1] = node2;
			this.number++;

			if (this.number <= bTreeOrder) {
				System.arraycopy(tempKeys, 0, this.keys, 0, this.number);
				System.arraycopy(tempChilds, 0, this.childs, 0, this.number);
				return null;
			}
			Integer middle = this.number / 2;
			BPlusNode tempNode = new BPlusNode();
			tempNode.number = this.number - middle;
			tempNode.parent = this.parent;
			if (this.parent == null) {
				BPlusNode tempBPlusNode = new BPlusNode<>();
				tempNode.parent = tempBPlusNode;
				this.parent = tempBPlusNode;
				oldKey = null;
			}

			System.arraycopy(tempKeys, middle, tempNode.keys, 0, tempNode.number);
			System.arraycopy(tempChilds, middle, tempNode.childs, 0, tempNode.number);
			for (int j = 0; j < tempNode.number; j++) {
				tempNode.childs[j].parent = tempNode;

			}
			this.number = middle;
			this.keys = new Object[maxNumber];
			this.childs = new Node[maxNumber];
			System.arraycopy(tempKeys, 0, this.keys, 0, middle);
			System.arraycopy(tempChilds, 0, this.childs, 0, middle);

			BPlusNode parentNode = (BPlusNode) this.parent;
			return parentNode.insertNode(this, tempNode, oldKey);

		}

	}

	class LeafNode> extends Node {

		protected Object[] values;
		protected LeafNode leftNode;
		protected LeafNode rightNode;

		public LeafNode() {
			super();
			this.values = new Object[maxNumber];
			this.leftNode = null;
			this.rightNode = null;
		}

		@Override
		T find(V key) {
			if (this.number <= 0)

				return null;
			Integer left = 0;
			Integer right = this.number;
			Integer middle = (left + right) / 2;
			while (left < right) {
				V middleKey = (V) this.keys[middle];
				if (key.compareTo(middleKey) == 0)
					return (T) this.values[middle];
				else if (key.compareTo(middleKey) < 0)
					right = middle;
				else
					left = middle;
				middle = (left + right) / 2;

			}
			return null;

		}

		@Override
		Node insert(T value, V key) {
			V oldKey = null;
			if (this.number > 0)
				oldKey = (V) this.keys[this.number - 1];
			int i = 0;
			while (i < this.number) {
				if (key.compareTo((V) this.keys[i]) < 0)
					break;
				i++;
			}

			Object tempKeys[] = new Object[maxNumber];
			Object tempValues[] = new Object[maxNumber];
			System.arraycopy(this.keys, 0, tempKeys, 0, i);
			System.arraycopy(this.values, 0, tempValues, 0, i);
			System.arraycopy(this.keys, i, tempKeys, i + 1, this.number - i);
			System.arraycopy(this.values, i, tempValues, i + 1, this.number - i);

			tempKeys[i] = key;
			tempValues[i] = value;
			this.number++;

			if (this.number <= bTreeOrder) {
				System.arraycopy(tempKeys, 0, this.keys, 0, this.number);
				System.arraycopy(tempValues, 0, this.values, 0, this.number);
				Node node = this;
				while (node.parent != null) {
					V tempKey = (V) node.keys[node.number - 1];
					if (tempKey.compareTo((V) node.parent.keys[node.parent.number - 1]) > 0) {
						node.parent.keys[node.parent.number - 1] = tempKey;
						node = node.parent;
					}
				}
				return null;
			}
			Integer middle = this.number / 2;
			LeafNode tempNode = new LeafNode();
			tempNode.number = this.number - middle;
			tempNode.parent = this.parent;
			if (this.parent == null) {
				BPlusNode tempBPlusNode = new BPlusNode<>();
				tempNode.parent = tempBPlusNode;
				this.parent = tempBPlusNode;
				oldKey = null;

			}
			System.arraycopy(tempKeys, middle, tempNode.keys, 0, tempNode.number);
			System.arraycopy(tempValues, middle, tempNode.values, 0, tempNode.number);

			this.number = middle;
			this.keys = new Object[maxNumber];
			this.values = new Object[maxNumber];
			System.arraycopy(tempKeys, 0, this.keys, 0, middle);
			System.arraycopy(tempValues, 0, this.values, 0, middle);

			this.rightNode = tempNode;
			tempNode.leftNode = this;

			BPlusNode parentNode = (BPlusNode) this.parent;

			return parentNode.insertNode(this, tempNode, oldKey);
		}

		@Override
		LeafNode refreshLeft() {
			if (this.number <= 0)
				return null;
			return this;
		}

	}

}

你可能感兴趣的:(算法,java)