2-3-4树

2-3-4树指拥有最多4个子节点3个数据项的多叉树。

对非叶节点,有3种可能的情况:

  1. 有一个数据项的节点,总有2个子节点
  2. 有两个数据项的节点,总有3个子节点
  3. 有三个数据项的节点,总有4个子节点

2-3-4树不允许一个节点只有一个子节点,要么没有(那就是叶节点),要么有2个及以上。

二叉树的规则是关键字比节点大的子节点,是右子节点,比父节点小的,是左子节点。2-3-4树的规则相似,但是加了以下几点:

  1. 根是child0的子树的所有子节点的关键字小于k0
  2. 根是child1的子树的所有子节点的关键字大于k0小于k1
  3. 根是child2的子树的所有子节点的关键字大于k1小于k2
  4. 根是child3的子树的所有子节点的关键字大于k2
    这里写图片描述

插入:找到满的节点就分裂,是叶子节点,就插入。都不是就去下一层。

2-3-4树和红黑树效率相近,缺点是有空间浪费。共同点是都通过旋转保持树的平衡。

代码:

public class DataItem {
    public long dData;

    public DataItem(long dData) {
        this.dData = dData;
    }

    public void displayItem() {
        System.out.print("/"+dData);
    }
}

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

    public void connectChild(int childNum,Node child){
        childArray[childNum]=child;
        if (child!=null){
            child.parent=this;
        }
    }
    public Node disconnectChild(int child){
        Node tempNode=childArray[child];
        childArray[child]=null;
        return tempNode;
    }
    public Node getChild(int childNum){
        return childArray[childNum];
    }
    public Node getChild(int childNum,boolean create){
        if (  create && childArray[childNum]==null){
            Node node=new Node();
            node.parent=this;
            childArray[childNum]=node;
        }
        return childArray[childNum];
    }
    public Node getParent(){
        return parent;
    }
    public boolean isLeaf(){
        return childArray[0]==null;
    }
    public int getNumItems(){
        return numItems;
    }
    public DataItem getItem(int index){
        return itemArray[index];
    }
    public boolean isFull(){
        return numItems==ORDER-1;
    }

    public int findItem(long key){
        for (int j=0;j<ORDER;j++){
            if (itemArray[j]==null){
                break;
            }else if (itemArray[j].dData==key){
                return j;
            }
        }
        return -1;
    }

    /**
     * 向节点中插入一个元素
     * @param newItem
     * @return
     */
    public int insertItem(DataItem newItem){
        numItems++;
        long newkey=newItem.dData;
        for (int j=ORDER-2;j>=0;j--){
            if (itemArray[j]==null){
                continue;
            }else {
                long itskey=itemArray[j].dData;
                if (newkey<itskey){
                    itemArray[j+1]=itemArray[j];
                }else {
                    itemArray[j+1]=newItem;
                    return j+1;
                }
            }
        }
        itemArray[0]=newItem;
        return 0;
    }
    public DataItem removeItem(){
        DataItem dataItem=itemArray[numItems-1];
        itemArray[numItems-1]=null;
        numItems--;
        return dataItem;
    }
    public void displayNode(){
        for (int j=0;j<numItems;j++){
            itemArray[j].displayItem();
            System.out.println("/");
        }
    }

}
public class Tree234 {
    private Node root=new Node();

    /**
     * 查找树中是否存在这个节点
     * @param key
     * @return
     */
    public int find(long key){
        Node curNode=root;
        int childNumber;
        while (true){
            if ((childNumber=curNode.findItem(key))!=-1){
                return childNumber;
            }else if (curNode.isLeaf()){
                return -1;
            }else {
                curNode=getNextChild(curNode,key);
            }
        }
    }
    public void insert(long dValue){
        Node curNode=root;
        DataItem tempItem=new DataItem(dValue);
        while (true){
            if (curNode.isFull()){
                spilt(curNode);
                curNode=curNode.getParent();
                curNode=getNextChild(curNode,dValue);
            }else if (curNode.isLeaf()){
                break;
            }else {
                curNode=getNextChild(curNode,dValue);//更换为孩子节点,那么curNode的parent节点一定是没有满的
            }
        }
        curNode.insertItem(tempItem);
    }

    private void spilt(Node curNode) {
        DataItem itemB,itemC;
        Node parent,child2,child3;
        int itemIndex;
        itemC=curNode.removeItem();
        itemB=curNode.removeItem();
        child2=curNode.disconnectChild(2);
        child3=curNode.disconnectChild(3);
        Node newRight=new Node();

        if (curNode==root){
            root=new Node();
            parent=root;
            root.connectChild(0,curNode);
        }else {
            parent=curNode.getParent();
        }
        itemIndex=parent.insertItem(itemB);
        int n=parent.getNumItems();
        for (int j=n-1;j>itemIndex;j--){
            Node temp=parent.disconnectChild(j);
            parent.connectChild(itemIndex+1,temp);
        }
        parent.connectChild(itemIndex+1,newRight);
        newRight.insertItem(itemC);
        newRight.connectChild(0,child2);
        newRight.connectChild(1,child3);
    }

    private Node getNextChild(Node curNode, long key) {
        int j;
        int numItems=curNode.getNumItems();
        for (j=0;j<numItems;j++){
            if (key<curNode.getItem(j).dData){
                return curNode.getChild(j);
            }
        }
        return curNode.getChild(j);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值