2-3数的add原理网上有大把的介绍
2-3树的添加代码在网上找到的不多
此代码一般没有什么实际用处
纯粹是个人喜好 记录一下
package com.test;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class _23TreeTest {
static class Node {
List<Integer> data;
List<Node> childs;
Node parent;
public Node(int e){
data = new ArrayList<>();
childs = new ArrayList<>();
data.add(e);
}
public Node(){
data = new ArrayList<>();
childs = new ArrayList<>();
}
}
static Node root = null;
static int size = 1000;
public static void main(String[] args) {
int[] arr = {7,9,3,5,2,6,8,4,1,11,15,19,13,12,16,17,18,10,14,21,20};
// Random r = new Random();
// int[] arr = new int[size];
// size = arr.length;
// for(int i=0;i<size;i++)
// arr[i]=r.nextInt(size)+i;
for(int e : arr)
add(e);
levelTravel(root);
}
/**
* 分层遍历打印
* @param root
*/
public static void levelTravel(Node root){
int h = 0, r = 0;
Node[] arr = new Node[size];
arr[r++] = root;
int nextLineIndex = r;
while(h<r){
Node n = arr[h++];
// @jdk1.8之上 使用
System.out.print(n.data.stream().map(o->o+"").collect(Collectors.joining(",")));//同一个节点中多个key使用逗号连接打印
System.out.print(" ");//不同节点使用空格隔开
for(int i=0;i<n.childs.size();i++)
arr[r++] = n.childs.get(i);
if(h == nextLineIndex){
nextLineIndex += r - h;
System.out.println();//分层换行
}
}
}
public static void add(int e){
/**
* 1、查找要插入的叶子节点
* 2、将节点按照顺序放到对应的data里面
* 3、递归判断节点是否需要拆分向上溢出
*/
/**step 1**/
Node target = findIndex4Add(e , root);
if(target != null)
recuAddNode(target , e);
}
private static void recuAddNode(Node target, int e) {
List<Integer> data = target.data;
Node p = target.parent;
List<Node> childs = target.childs;
/**step 2**/
if(data.size() == 0)
data.add(e);
else if(data.size() == 1){
if(e < data.get(0))
data.add(0, e);
else
data.add(e);
}else{
if(e < data.get(0))
data.add(0, e);
else if(e > data.get(1))
data.add(e);
else
data.add(1,e);
}
/**step 3**/
if(data.size() == 3){
/**
* 需要溢出父亲节点
* 处理好 当前节点和父节点 , 当前节点和子节点 关系即可
*/
int needOver = data.get(1);
if(p == null){
p = new Node();
root = p;
}
Node l = new Node(data.get(0));
Node r = new Node(data.get(2));
l.parent = p;
r.parent = p;
//当前节点如果有子节点,则子节点个数为4,需要分离子节点
if(childs.size() > 0){
for(int i=0 ; i<childs.size() ; i++){
if(i<2){
l.childs.add(childs.get(i));
childs.get(i).parent = l;
}else{
r.childs.add(childs.get(i));
childs.get(i).parent = r;
}
}
}
int index = p.childs.indexOf(target);
int sibs = p.childs.size();
p.childs.remove(target);
if(sibs == 0){
p.childs.add(l);
p.childs.add(r);
}else if(sibs == 2){
if(index == 0){
p.childs.add(0,r);
p.childs.add(0,l);
}
else{
p.childs.add(l);
p.childs.add(r);
}
}else if(sibs == 3){
if(index == 0){
p.childs.add(0,r);
p.childs.add(0,l);
}else if(index == 1){
p.childs.add(1,r);
p.childs.add(1,l);
}else{
p.childs.add(l);
p.childs.add(r);
}
}
recuAddNode(p , needOver);
}
}
/**
* 找到需要插入的位置 注意是需要插入的位置 , 而不是查询
* @param e
* @param node
* @return
*/
public static Node findIndex4Add(int e , Node node){
if(node == null){
root = new Node();
return root;
}
if(node.childs.size() == 0)
return node;
List<Integer> data = node.data;
List<Node> childs = node.childs;
if(data.size() == 1){
if(e < data.get(0)){
return findIndex4Add(e , childs.get(0));
}else if(e > data.get(0)){
return findIndex4Add(e , childs.get(1));
}else
return null; //已存在就不需要插入了
} else if(data.size() == 2){
if(e < data.get(0)){
return findIndex4Add(e , childs.get(0));
}else if(e > data.get(0) && e < data.get(1)){
return findIndex4Add(e , childs.get(1));
}else if(e > data.get(1)){
return findIndex4Add(e , childs.get(2));
}else
return null; //已存在就不需要插入了
}else
throw new RuntimeException("超出范围");
}
}
代码可直接运行看到结果