写的匆忙 估计有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的更多相关文章

  1. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  2. SAP CRM 树视图(TREE VIEW)

    树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...

  3. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

  4. 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  5. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  6. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  7. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  8. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  9. Leetcode 笔记 101 - Symmetric Tree

    题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...

  10. Tree树节点选中及取消和指定节点的隐藏

    指定节点变色 指定节点隐藏 单击节点 未选中则选中该节点 已选中则取消该节点 前台: 1.HTML <ul id="listDept" name="listDept ...

随机推荐

  1. CSS的水平居中和垂直居中解决方案

    在写CSS样式的时候,有时为了美观,会添加水平居中和垂直居中,这时候你有可能会遇到很棘手的问题,有些水平居中和垂直居中的属性添加上去完全没反应,下面给大家列举一些CSS水平居中和垂直居中的终极解决方案 ...

  2. 2015北京网络赛 G Boxes BFS+打表

    G Boxes 题意:n个位置摆有n个箱子,每次移动只能把相邻的垒起来,且上面的必须小于下面的.求摆成升序需要移动多少步. 思路:这里的n很小,只有7.但是bfs最快的情况需要2s左右,所以就打表了. ...

  3. vue.js路由vue-router(一)——简单路由基础

    前言 vue.js除了拥有组件开发体系之外,还有自己的路由vue-router.在没有使用路由之前,我们页面的跳转要么是后台进行管控,要么是用a标签写链接.使用vue-router后,我们可以自己定义 ...

  4. 【转】Flash AS3.0 中的自定义事件

    原文 http://www.cnblogs.com/acpp/archive/2010/10/19/1855670.html package { import flash.events.Event; ...

  5. CentOS下安装.net core环境并部署WebAPI

    1.安装CentOS 7 2.安装.net Core 2环境,参考官方文档:(建议采用SDK (tar.gz)安装) https://www.microsoft.com/net/download/li ...

  6. Cocos2d-x手机游戏开发与项目实践具体解释_随书代码

    Cocos2d-x手机游戏开发与项目实战具体解释_随书代码 作者:沈大海  因为原作者共享的资源为UTF-8字符编码.下载后解压在win下显示乱码或还出现文件不全问题,现完整整理,解决全部乱码问题,供 ...

  7. leetCode 82.Remove Duplicates from Sorted List II (删除排序链表的反复II) 解题思路和方法

    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...

  8. 使用cocos2dx 3.2和cocosstudio屏幕适配总结----相对布局

    屏幕适配的文章太多了,基本上都是理论性的东西.大家明确了机制就知道了.没有完美的适配方案,除非你们的美工愿意折腾. 常规策略: 今天研究了一下屏幕适配导致的缩放和展示不全的问题(黑边的方案直接淘汰). ...

  9. 关于bootstrap IE8的兼容性问题

    非常久没有写技术类的文章了.这几天在用bootstrap来做我们站点的UI框架,感觉还是不错的.只是遇到一点不大不小的问题,那就是有朋友在IE8下訪问我们的站点.界面变成了跟手机浏览一样的界面. 后来 ...

  10. 我的RTOS 之二 --Threadx在skyeye上仿真測试(基于2410)

    对于RTOS 移植来说,移植平台至少要提供双方面的设备. 1.OS执行时,须要tick,所以须要提供Timer定时器 2.OS执行时,须要调度,就是挂起当前线程,把控制权交给系统,所以须要訪问系统各个 ...