之前想实现红黑树来着,发现红黑树在遵循平衡二叉树规则的前提下,更多是2-3-4B树的二叉树形式实现
思路
2-3-4B树构造思路基于B树规则的基础之上,加上了每节点至多三个数值的限制。
插入
其插入规则于二叉查找树类似,小于则向左传递,反之则向右。传递至叶子节点时进行插入操作,若当前叶子节点已经满了,则需要向父节点传递最接近父节点的值的值,若没有父节点则选取第二或第三个节点抽离为父节点,其左右节点变为该父节点的左右子树。
代码实现
参数构造
num1~num4从小到大视为节点的四个值,当4个值都存满时,则向上传递一个节点,或裂解为一组新的树
依据常规下至多三个值的要求,建立左,中左,中右,右四棵子树,和一个父节点
private int num1=-1;
private int num2=-1;
private int num3=-1;
private int num4=-1;
//父亲节点
private Point parent=null;
private Point right=null;
private Point midRight=null;
private Point midLeft=null;
private Point left=null;
插入方法
插入方法为将值依次与num1~num4比较,小向右,大向左,有子树则传递至子树,无子树则插入自身,满4个则向上传递或裂解
public void add(int num){
//空节点
if(this.num1==-1){
this.num1 = num;
}
//单节点
if(this.num1!=-1 && this.num2==-1){
if(this.num1>num){
toLeftPoint(num);
}
if(this.num1<num){
this.num2 = num;
}
}
//双节点
if(this.num1!=-1 && this.num2!=-1 && this.num3==-1){
if(this.num1>num){
toLeftPoint(num);
}
if(this.num1<num && this.num2>num){
toMidLeft(num);
}
if(this.num2<num){
this.num3 = num;
}
}
//满节点
if(this.num1!=-1 && this.num2!=-1 && this.num3!=-1){
if(this.num1>num){
toLeftPoint(num);
}
if(this.num1<num && this.num2>num){
toMidLeft(num);
}
if(this.num2<num && this.num3>num){
toMidRight(num);
}
if(this.num3<num){
toRight(num);
}
if(parent==null){
divid();//节点裂解
}
if(parent!=null){
sendToParent();//传递至父亲节点
}
}
}
private void toRight(int num){
if(this.getRight()!=null){
this.getRight().add(num);
}else{
Point p = new Point();
p.add(num);
this.setRight(p);
}
}
private void toMidRight(int num){
if(this.getMidRight()!=null){
this.getMidRight().add(num);
}else{
Point p = new Point();
p.add(num);
this.setMidRight(p);
}
}
private void toMidLeft(int num){
if(this.getMidLeft()!=null){
this.getMidLeft().add(num);
}else{
Point p = new Point();
p.add(num);
this.setMidLeft(p);
}
}
private void toLeftPoint(int num){
if(this.getLeft()!=null){
this.getLeft().add(num);
}else{
Point p = new Point();
p.add(num);
this.setLeft(p);
}
}
节点裂解
取当前节点的第二个值为父节点,左和中左子树为新左节点的左右子树,中右和右子树为新右子树的中右和右子树,若没有则为null传递,不用管
//当当前节点数值达到4个之后,且无父节点时需将该节点裂解为三个
private void divid(){
//构造新的父亲节点
Point newParent = new Point();
newParent.add(this.num2);
//构造新的左节点
Point newLeft = new Point();
newLeft.add(this.num1);
newLeft.setLeft(this.left);
newLeft.setRight(this.midLeft);
newLeft.parent = newParent;
newParent.setLeft(newLeft);
//构造新的右节点
Point newRight = new Point();
newRight.add(this.num3);
newRight.add(this.num4);
newRight.setRight(this.right);
newRight.setMidRight(this.midRight);
newRight.parent = newParent;
newParent.setRight(newRight);
}
值的向上传递
判断该节点位于父节点的哪一个位置,传递相应值至父节点
//当当前节点数达到4个之后,且有父节点时需要向上传递数据
private void sendToParent(int num){
//判断该节点处于父节点四分分支中的哪一个分支
if(this.parent.getLeft().equals(this)){
//处于左节点
this.parent.setToParent(this.num4);
this.num4 = -1;
}else{
this.parent.sendToParent(this.num1);
this.num1 = this.num2;
this.num2 = this.num3;
this.num3 = this.num4;
this.num4 = -1;
}
}
全部代码
package TTFBTree;
public class Point {
private int num1=-1;
private int num2=-1;
private int num3=-1;
private int num4=-1;
//父亲节点
private Point parent=null;
private Point right=null;
private Point midRight=null;
private Point midLeft=null;
private Point left=null;
public void add(int num){
//空节点
if(this.num1==-1){
this.num1 = num;
}
//单节点
if(this.num1!=-1 && this.num2==-1){
if(this.num1>num){
toLeftPoint(num);
}
if(this.num1<num){
this.num2 = num;
}
}
//双节点
if(this.num1!=-1 && this.num2!=-1 && this.num3==-1){
if(this.num1>num){
toLeftPoint(num);
}
if(this.num1<num && this.num2>num){
toMidLeft(num);
}
if(this.num2<num){
this.num3 = num;
}
}
//满节点
if(this.num1!=-1 && this.num2!=-1 && this.num3!=-1){
if(this.num1>num){
toLeftPoint(num);
}
if(this.num1<num && this.num2>num){
toMidLeft(num);
}
if(this.num2<num && this.num3>num){
toMidRight(num);
}
if(this.num3<num){
toRight(num);
}
if(parent==null){
divid();//节点裂解
}
if(parent!=null){
sendToParent(this.num1);//传递至父亲节点
}
}
}
private void toRight(int num){
if(this.getRight()!=null){
this.getRight().add(num);
}else{
Point p = new Point();
p.add(num);
this.setRight(p);
}
}
private void toMidRight(int num){
if(this.getMidRight()!=null){
this.getMidRight().add(num);
}else{
Point p = new Point();
p.add(num);
this.setMidRight(p);
}
}
private void toMidLeft(int num){
if(this.getMidLeft()!=null){
this.getMidLeft().add(num);
}else{
Point p = new Point();
p.add(num);
this.setMidLeft(p);
}
}
private void toLeftPoint(int num){
if(this.getLeft()!=null){
this.getLeft().add(num);
}else{
Point p = new Point();
p.add(num);
this.setLeft(p);
}
}
//当当前节点数达到4个之后,且有父节点时需要向上传递数据
private void sendToParent(int num){
//判断该节点处于父节点四分分支中的哪一个分支
if(this.parent.getLeft().equals(this)){
//处于左节点
this.parent.setToParent(this.num4);
this.num4 = -1;
}else{
this.parent.sendToParent(this.num1);
this.num1 = this.num2;
this.num2 = this.num3;
this.num3 = this.num4;
this.num4 = -1;
}
}
//从子节点抽象数据
private void setToParent(int num){
if(num < this.num1){
this.num4 = this.num3;
this.num3 = this.num2;
this.num2 = this.num1;
this.num1 = num;
}
if(this.num1<num && num < this.num2){
this.num4 = this.num3;
this.num3 = this.num2;
this.num2 = num;
}
if(this.num2<num && num< this.num3){
this.num4 = this.num3;
this.num3 = num;
}
if(this.num3<num){
this.num4 = num;
}
if(this.num4!=-1){
divid();
}
}
//当当前节点数值达到4个之后,且无父节点时需将该节点裂解为三个
private void divid(){
//构造新的父亲节点
Point newParent = new Point();
newParent.add(this.num2);
//构造新的左节点
Point newLeft = new Point();
newLeft.add(this.num1);
newLeft.setLeft(this.left);
newLeft.setRight(this.midLeft);
newLeft.parent = newParent;
newParent.setLeft(newLeft);
//构造新的右节点
Point newRight = new Point();
newRight.add(this.num3);
newRight.add(this.num4);
newRight.setRight(this.right);
newRight.setMidRight(this.midRight);
newRight.parent = newParent;
newParent.setRight(newRight);
}
public int getMax(){
if(this.num3!=-1){
return this.getNum3();
}
if(this.num2!=-1){
return this.getNum2();
}
if(this.num1!=-1){
return this.getNum1();
}
return -1;
}
public int getMin(){
return this.num1;
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public int getNum3() {
return num3;
}
public void setNum3(int num3) {
this.num3 = num3;
}
public int getNum4() {
return num4;
}
public void setNum4(int num4) {
this.num4 = num4;
}
public Point getRight() {
return right;
}
public void setRight(Point right) {
this.right = right;
}
public Point getMidRight() {
return midRight;
}
public void setMidRight(Point midRight) {
this.midRight = midRight;
}
public Point getMidLeft() {
return midLeft;
}
public void setMidLeft(Point midLeft) {
this.midLeft = midLeft;
}
public Point getLeft() {
return left;
}
public void setLeft(Point left) {
this.left = left;
}
public Point getParent() {
return parent;
}
public void setParent(Point parent) {
this.parent = parent;
}
}