BPX-tree
写的匆忙 估计有BUG 修改后 会去掉这个 说明
/**
* @author shuly
* @date 2017/6/5.
*/ // hint 一日为叶,终身为叶, 最后还是要转换成 <链表存储节 | 数组> 比较快, 自己写个链表吧
// 先写一个数组的好用一点
class Config {
static int M = 8; // 写的不好请确保这是个偶数.
static int MIN_NUM = M / 2;
} class LinkData {
LinkData next;
Entry data;
LinkData(){
next = null;
data = null;
}
} class Node {
int m;
Node left;
Node right;
Entry[] children = new Entry[Config.M];
//LinkData children = new LinkData();
Node(int k) {
m = k;
left = null;
right = null;
}
} abstract class Entry {
Comparable key;
} class EntryLeaf extends Entry {
Object val; EntryLeaf(Comparable key, Object val) {
this.key = key;
this.val = val;
}
} class EntryNotLeaf extends Entry {
Node nextNode; EntryNotLeaf(Comparable key, Node next) {
this.nextNode = next;
this.key = key;
} } public class BPXTree<Key extends Comparable<Key>, Value> {
private int height;
private int total;
private Node root;
// todo push
private Node leafNodeHead; public BPXTree() { leafNodeHead = new Node(0);
root = new Node(0);
leafNodeHead.right = root;
root.left = leafNodeHead;
} public int insert(Key key, Value value) {
if (key == null) throw new IllegalArgumentException("插入空值我操");
++total;
Node u = insert(root, key, value, height);
if (u != null) {
Node t = new Node(2);
t.children[0] = new EntryNotLeaf(root.children[0].key, root);
t.children[1] = new EntryNotLeaf(u.children[0].key, u);
root = t;
++height; // 树的生长
}
return 1;
} /**
* @param now 当前插入节点
* @param key key
* @param value value
* @param h 高度
* @return 需要分裂则但会当前节点,否则是null
*/
private Node insert(Node now, Key key, Value value, int h) {
int j;
Entry tmp; if (h == 0) { // 叶子节点
tmp = new EntryLeaf(key, value);
for (j = 0; j < now.m; ++j) {
if (less(key, now.children[j].key)) {
break;
}
}
} else { // 非叶子节点
tmp = new EntryNotLeaf(key, null);
for (j = 0; j < now.m; ++j) {
if ((j + 1 == now.m) || less(key, now.children[j + 1].key)) {
Node u = insert(((EntryNotLeaf) now.children[j++]).nextNode, key, value, h - 1);
if (u == null) return null;
tmp.key = u.children[0].key;
((EntryNotLeaf) tmp).nextNode = u;
break;
}
}
}
// 挪地方
for (int i = now.m; i > j; --i) {
now.children[i] = now.children[i - 1];
}
now.children[j] = tmp;
now.m++;
if (now.m < Config.M) {
return null;
}
return split(now);
} private static Node split(Node now) {
int base = Config.M / 2;
Node tmp = new Node(base);
now.m = base;
for (int j = 0; j < base; ++j) {
tmp.children[j] = now.children[base + j];
now.children[base + j] = null;
}
tmp.right = now.right;
tmp.left = now;
now.right = tmp;
return tmp;
} public Value query(Key key) {
if (key == null) {
throw new IllegalArgumentException("查询值是空啊");
}
return query(root, key, height);
} /**
* @param now 当前节点
* @param key 插入的值
* @param h 当前高度
* @return key对应的value, 没有就是null;
*/
private Value query(Node now, Key key, int h) {
Entry[] children = now.children;
if (h == 0) {// 叶子节点
for (int j = 0; j < now.m; ++j) {
if (eq(key, children[j].key)) {
return (Value) ((EntryLeaf) children[j]).val;
}
}
} else { // 非叶子节点
for (int j = 0; j < now.m; ++j) {
if ((j + 1 == now.m) || less(key, children[j + 1].key)) {
return query(((EntryNotLeaf) children[j]).nextNode, key, h - 1);
}
}
}
return null;
} public Queue<Value> queue(Key left, Key right) {
Queue<Value> ans = new LinkedList<>();
query(root, left, right, height, ans);
return ans;
} // todo
private void query(Node now, Key left, Key right, int h, Queue<Value> ans) { } /**
* @param key 删除的关键字
* @return 删除的内容;
* <p>
* <p>
* 切记在合并的时候 要去要别的节点,而不是自己的给别人,也不能去和自己的堂兄弟借,要找兄弟合并。
* 这样才能 递归的更新 索引. 3Q
*/
public Value delete(Key key) {
// root 节点的size没有限制
Triple<Value, Boolean, Key> ans = delete(root, key, height);
return ans.first;
} /**
* @param now 当前节点
* @param key 删除的主键
* @param h 目前的高度
* @return <删除的 映射值, 修改的儿子节点是否足够用, 抢的节点>
* <p>
* <p>
* 采用自己先去抢,抢不到在让父亲节点调度的方式.
*/
public Triple<Value, Boolean, Key> delete(Node now, Key key, int h) {
Triple<Value, Boolean, Key> ans = new Triple<>(null, null, null);
if (h == 0) {
//叶子了
for (int i = 0; i < now.m; i++) {
if (eq(key, now.children[i].key)) {
ans.first = (Value) ((EntryLeaf) now.children[i]).val;
now.m--;
for (int j = i; j < now.m; j++) {
now.children[j] = now.children[j + 1];
}
now.children[now.m] = null; // 删除吗 不可能 越界
break;
}
}
} else {
// 非叶子 节点
// 狗儿子们开始干活了.
for (int i = 0; i < now.m; i++) {
if ((i + 1 == now.m) || less(key, now.children[i + 1].key)) {
// 去吧比卡丘
ans = delete(((EntryNotLeaf) now.children[i]).nextNode, key, h - 1); if (ans.second) {
// 操 欲求不满的东西,让我来施舍你! 妈的我 还要维护你们的链接信息,我了个去,
int source;
int target = i; if (i + 1 == now.m && i != 0) {
source = i - 1;
Node sourceNode = ((EntryNotLeaf) now.children[source]).nextNode;
Node targetNode = ((EntryNotLeaf) now.children[target]).nextNode; for (int w = 0; w < targetNode.m; ++w) {
targetNode.children[w + sourceNode.m] = targetNode.children[w];
} for (int s = 0; s < sourceNode.m; s++) {
targetNode.children[s] = sourceNode.children[s];
}
targetNode.m += sourceNode.m; if(sourceNode.left != null) {
sourceNode.left.right = targetNode;
}
targetNode.left = sourceNode.left;
} else {
source = i + 1; if (source == now.m) {
// 结束了 这是root节点
this.root = ((EntryNotLeaf)root.children[0]).nextNode;
this.height--;
return ans;
}
Node sourceNode = ((EntryNotLeaf) now.children[source]).nextNode;
Node targetNode = ((EntryNotLeaf) now.children[target]).nextNode;
for (int s = 0, t = targetNode.m; s < sourceNode.m; s++, t++) {
targetNode.children[t] = sourceNode.children[s];
}
targetNode.m += sourceNode.m;
targetNode.right = sourceNode.right;
if(sourceNode.right != null) {
sourceNode.right.left = targetNode;
}
} // 再见我 的 小伙伴, 满足了你,牺牲了他,何必同室操戈,
for (int s = source; s < now.m; s++) {
now.children[s] = now.children[s + 1];
}
now.m--;
now.children[now.m] = null;
// 抢东西更新
} else if (ans.third != null && i + 1 != now.m && ans.third.compareTo((Key) now.children[i + 1].key) == 0) {
// 借东西索引更新
now.children[i + 1].key = updateIndexUntil(((EntryNotLeaf) now.children[i + 1]).nextNode, ans.third);
now.children[i].key = ((EntryNotLeaf)now.children[i]).nextNode.children[0].key;
} else {
now.children[i].key = ((EntryNotLeaf)now.children[i]).nextNode.children[0].key;
}
//now.children[i].key = ((EntryNotLeaf)now.children[i]).nextNode.children[0].key;
break;
}
}
}
ans.second = false;
if (now.m < Config.MIN_NUM) { //卧槽节点不够了
if (now.left != null && now.left.m > Config.MIN_NUM) {
// left 请给我点吧,我不行了QAQ
now.left.m--;
Entry entry = now.left.children[now.left.m];
now.left.children[now.left.m] = null; // 这个刁钻的插入操作妈的
for (int i = 1; i <= now.m; ++i) {
now.children[i] = now.children[i - 1];
}
now.children[0] = entry;
now.m++;
ans.third = (Key) entry.key;
} else if (now.right != null && now.right.m > Config.MIN_NUM) {
// right 请给我点吧,我不行了QAQ
Entry entry = now.right.children[0];
now.right.m--;
for (int i = 0; i < now.right.m; ++i) {
now.right.children[i] = now.right.children[i + 1];
}
now.right.children[now.right.m] = null; now.children[now.m] = entry;
now.m++;
// 这个要更新那边 等待到LCA
ans.third = (Key) entry.key;
} else {
// 父亲啊,请给我做主,灭了他们其中一个要不我不满足
ans.second = true;
}
}
return ans;
} private Key updateIndexUntil(Node now, Key key) {
if (now.children[0].key.compareTo(key) == 0) {
now.children[0].key = updateIndexUntil(((EntryNotLeaf)now.children[0]).nextNode, key);
}
return (Key) now.children[0].key;
} @Override
public String toString() {
return toString(root, height, "") + "\n";
} private String toString(Node h, int ht, String indent) {
StringBuilder s = new StringBuilder();
Entry[] children = h.children;
if (ht == 0) {
for (int j = 0; j < h.m; j++) {
s.append(indent).append(children[j].key).append(" ").append(((EntryLeaf) children[j]).val).append("\n");
}
} else {
for (int j = 0; j < h.m; j++) {
s.append(indent).append("(").append(children[j].key).append(")").append("\n");
s.append(toString(((EntryNotLeaf) children[j]).nextNode, ht - 1, indent + " "));
}
}
return s.toString();
} private static boolean less(Comparable k1, Comparable k2) {
return k1.compareTo(k2) < 0;
} private static boolean eq(Comparable k1, Comparable k2) {
return k1.compareTo(k2) == 0;
} private void linkOut() {
Node head = this.leafNodeHead;
while (head != null) { for (int i = 0; i < head.m; i++) {
System.out.print(head.children[i].key + " : " + ((EntryLeaf) head.children[i]).val + '\t');
}
head = head.right;
}
} public static void main(String[] args) {
BPXTree<Integer, Long> st = new BPXTree<>();
for (int i = 1; i <= 20; i++) {
st.insert(i, (long) i);
}
Long value = st.delete(10);
Long pp = st.delete(9);
pp = st.delete(3);
pp = st.delete(6);
pp = st.delete(1);
pp = st.delete(4);
pp = st.delete(7);
pp = st.delete(2);
pp = st.delete(8);
pp = st.delete(5); pp = st.delete(11);
pp = st.delete(12);
pp = st.delete(16);
pp = st.delete(17); System.out.println("START");
System.out.println(st.toString());
System.out.println("END");
st.linkOut(); pp = st.delete(18); System.out.println("START");
System.out.println(st.toString());
System.out.println("END");
st.linkOut();
pp = st.delete(19);
pp = st.delete(20);
pp = st.delete(13);
pp = st.delete(14);
System.out.println("START");
System.out.println(st.toString());
System.out.println("END");
st.linkOut();
pp = st.delete(15); System.out.println("START");
System.out.println(st.toString());
System.out.println("END");
st.linkOut();
}
}
BPX-tree的更多相关文章
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- SAP CRM 树视图(TREE VIEW)
树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...
- 无限分级和tree结构数据增删改【提供Demo下载】
无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...
- 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
- Leetcode 笔记 110 - Balanced Binary Tree
题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...
- Leetcode 笔记 100 - Same Tree
题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...
- Leetcode 笔记 99 - Recover Binary Search Tree
题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...
- Leetcode 笔记 98 - Validate Binary Search Tree
题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...
- Leetcode 笔记 101 - Symmetric Tree
题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...
- Tree树节点选中及取消和指定节点的隐藏
指定节点变色 指定节点隐藏 单击节点 未选中则选中该节点 已选中则取消该节点 前台: 1.HTML <ul id="listDept" name="listDept ...
随机推荐
- 14.idea右键单击没有 svn选项处理办法
转自:http://www.cnblogs.com/xiohao/p/5044213.html 问题一: IntelliJ IDEA打开带SVN信息的项目不显示SVN信息,项目右键SVN以及图标还有C ...
- Web API总结
1.Web API 控制器(Controller) 继承ApiController 2. Api 的 Url Map: api/{controller}/{id} 每个"Action&quo ...
- 学习《TensorFlow实战Google深度学习框架 (第2版) 》中文PDF和代码
TensorFlow是谷歌2015年开源的主流深度学习框架,目前已得到广泛应用.<TensorFlow:实战Google深度学习框架(第2版)>为TensorFlow入门参考书,帮助快速. ...
- php https链接
1.安装soap扩展 2.安装openssL 3.代码执行 function issure($sn){//通过soap链接接口 进行确认是否是正确的sn码 try{ $clie ...
- spring在web.xml中的配置
在实际项目中spring的配置文件applicationcontext.xml是通过spring提供的加载机制,自动加载的容器中去,在web项目中,配置文件加载到web容器中进行解析,目前,sprin ...
- Vijos——T 1082 丛林探险
https://vijos.org/p/1082 描述 东非大裂谷中有一片神秘的丛林,是全世界探险家的乐园,著名黄皮肤探险家BB一直想去试试.正好我国科学家2005年4月将首次对东非大裂谷进行科考,B ...
- C++里的模板
1.泛型编程 --即实现一个通用的标准容器库. 所谓通用的标准容器库,就是要做到:比方List类存放全部肯恩类型的对象这样的事:泛型编程让你编写一个全然一般化并可反复使用的算法,其效率与针对某特定数 ...
- PostgreSQL递归查询实现树状结构查询
在Postgresql的使用过程中发现了一个非常有意思的功能,就是对于须要相似于树状结构的结果能够使用递归查询实现.比方说我们经常使用的公司部门这样的数据结构.一般我们设计表结构的时候都是相似以下的S ...
- 正确地在QML应用中使用fontsize
我们知道我们有时须要显示text文本.可是,在QML应用中.我们应该怎样选择font的大小呢?在今天的这篇文章中,我们将展示在Ubuntu平台中的不同文字的大小.我们能够通过FontUtils来帮我们 ...
- 调用google翻译
1. [代码]maven依赖 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <dependency> <groupId>org.a ...