2-3-4树(java实现)

  1. 什么是2-3-4树?
    每个节点最多包含三个数据项,4个子节点
    数据项按顺序排列
    子节点的数据项,按此节点数据项按顺序寻找并按顺序插入到子节点
    在这里插入图片描述
  2. 查找
    和二叉树不同的是,每一个节点含有三个数据项,因此每到一个节点都会进行1-3次比较,因此查找的效率是m*log(N+1), m是每个节点的平均数据项的个数
  3. 插入
    但在插入过程中遇到满结点时,就需要产生分裂,分裂后再继续向下查找到叶子节点并插入
  4. 分裂
    分裂分两种情况,一种是根节点满如图
    在这里插入图片描述
    还有一种是子节点满,如图
    在这里插入图片描述
    会发现按以上规则分裂及插入 左右子树的高度是相同的
package Data.Tree234.structure;

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

public class Tree234Code{
    public static void main(String[] args) throws Exception{
        Tree234 tree = new Tree234();
        tree.insert(new DataItem(13));
        tree.insert(new DataItem(24));
        tree.insert(new DataItem(34));
        tree.insert(new DataItem(23));
        tree.insert(new DataItem(98));
        tree.insert(new DataItem(45));
        tree.insert(new DataItem(75));
        tree.insert(new DataItem(46));
        tree.insert(new DataItem(30));
        tree.insert(new DataItem(12));
        tree.insert(new DataItem(2));

        tree.levelTraverse();
        
//        /13/24/45
//        /2/12
//        /23
//        /30/34
//        /46/75/98
    }
}

class Tree234{
    Node root = new Node();

    public DataItem find(int value){
        Node node = root;
        while(node != null){
            DataItem item = node.findItem(value);
            if(item == null){
                node = node.getNextNode(value);
            }else{
                return item;
            }
        }
        return null;
    }

    public void insert(DataItem item){
        Node node = root;
        while(node != null){
            if(node.isFull()){
                // 当遇到满节点时 进行分裂
                split(node);
                //重新找应该往左还是右子树查找
                node = node.getParent().getNextNode(item.getValue());
            }else if(node.isLeaf()){
                //找到叶子了
                break;
            }else{
                //继续往下找
                node = node.getNextNode(item.getValue());
            }
        }
        node.insertItem(item);
    }

    public void split(Node node){
        DataItem item1 = node.remove(1);
        DataItem item2 = node.remove(2);
        Node child2 = node.disconnect(2);
        Node child3 = node.disconnect(3);

        Node newRight = new Node();
        newRight.insertItem(item2);
        newRight.connect(0, child2);
        newRight.connect(1, child3);

        if(node == root){
            //当根节点满时
           root = new Node();
           root.insertItem(item1);
           root.connect(0, node);
           root.connect(1, newRight);
           node.setParent(root);
           newRight.setParent(root);
        }else {
            //子节点
            int loc = node.getParent().insertItem(item1);
            Node parent = node.getParent();
            int i;
            for(i = node.getParent().getNumItems(); i > loc + 1; i--){
                parent.connect(i, parent.getChild(i-1));
            }
            node.getParent().connect(i, newRight);
            newRight.setParent(parent);
        }
        //可以发现插入时  树是向上长高的
    }

    public void levelTraverse() throws InterruptedException {
        if(root == null){return;}
        //利用对列进行层序遍历
        Queue<Node> que = new ArrayBlockingQueue<Node>(20);
        ((ArrayBlockingQueue<Node>) que).put(root);
        while(!que.isEmpty()){
            Node node = que.poll();
            node.displayNode();
            if(!node.isLeaf()){
                for(int i = 0; i <= node.getNumItems(); i++){
                    ((ArrayBlockingQueue<Node>) que).put(node.getChild(i));
                }
            }
        }
    }
}

class Node{
    private static final int ORDER = 4;
    private int numItems = 0;
    private Node parent;
    private Node childArray[] = new Node[ORDER];
    private DataItem itemArray[] = new DataItem[ORDER-1];

    public DataItem findItem(int value){
        for(DataItem item : itemArray){
           if(item.getValue() == value){
               return item;
           }
        }
        return null;
    }

    public void displayNode(){
        for(int i = 0; i < numItems; i++){
            System.out.print(itemArray[i]);
        }
        System.out.println();
    }

    public int getNumItems(){
        return numItems;
    }

    public Node getChild(int index){
        return childArray[index];
    }

    public DataItem remove(int index){
        DataItem item = itemArray[index];
        itemArray[index] = null;
        numItems--;
        return item;
    }

    public Node disconnect(int index){
        Node node = childArray[index];
        childArray[index] = null;
        return node;
    }

    public void connect(int index, Node node){
        childArray[index] = node;
    }

    public Node getParent(){
        return parent;
    }

    public void setParent(Node node){
        parent = node;
    }

    public boolean isFull(){
        return numItems == 3;
    }

    public int insertItem(DataItem item){
        int i = 0;
        for(; i < numItems; i++){
            if(item.getValue() < itemArray[i].getValue()){
                for(int j = numItems; j > i; j--){
                    itemArray[j] = itemArray[j-1];
                }
                break;
            }else if(item.getValue() == itemArray[i].getValue()){
                return -1;
            }
        }
        itemArray[i] = item;
        numItems++;
        //返回插入节点的位置
        return i;
    }

    public Node getNextNode(int value){
        for(int i = 0; i < numItems; i++){
            if(value < itemArray[i].getValue()){
                return childArray[i];
            }
        }
        return childArray[numItems];
    }

    public boolean isLeaf(){
        return childArray[0] == null;
    }
}

class DataItem{
    private int value;

    public DataItem(int v){
        value = v;
    }

    @Override
    public String toString(){
        return "/" + value;
    }

    public int getValue(){
        return value;
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值