2013.12.24

* 实现2-3-4树

* 2-3-4树的查找效率与红-黑树接近,都是O(logN);由于使用数组,存储空间浪费现象比较严重,大约有2/7;红-黑树是平衡树,几乎每个结点的子结点存储空间都被利用了,因此存储效率高。

* 测试用例在程序中的重要性

  测试用例要尽可能的覆盖到if条件语句的所有情况;本例中,要测试到结点分裂时从不同位置插入到父结点时的情况;

  用大量的random数据测试;100/1000;

  从上至下插入结点时,边寻找下一跳结点,边判断当前结点是否为满结点

* 若发现当前结点为满结点,有两种情况:

    1. 当前结点为根结点,执行split()分裂之后,因为根结点分裂会产生一个新的根结点,所以不能通过node=prev回到上层结点,所以需要node=root;

    2. 当前结点不是根结点,执行split()分裂之后,node=prev,回到上一层结点;

    若不回到上一层结点,会导致新插入的数据不能进入正确的位置;

* 对当前结点执行split()分裂操作,有两种情况:

  1. 当前结点为根结点,新建两个结点;

  2. 当前结点不是根结点,则新建一个结点,当前结点的右侧结点转移到新建的结点上,当前结点的中间结点转移到父结点;

      插入到父结点时,会有5种情况:

      1) 父结点插入前只有一个结点,插入位置在唯一结点的左侧;

      2) 父结点插入前只有一个结点,插入位置在唯一结点的右侧;

      3) 父结点插入前有两个结点,插入位置在左侧结点的左侧;

      4) 父结点插入前有两个结点,插入位置在两个结点的中间;

      5) 父结点插入前有两个结点,插入位置在右侧结点的右侧;

     可以通过 

       for(int i=node.parent.current; i>ptr; i--) node.parent.nArr[i+1]=node.parent.nArr[i];

       node.parent.nArr[ptr+1]=newNode;  

     实现

* 2-3-4树@java/DataStructure/unit10

class Tree234{
	public Node root;

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

	public Tree234(Node root){
		this.root=root;
	}

	public DataItem find(DataItem data){
		Node node=root;
		while(node!=null){
			DataItem temp=node.findItem(data);
			if(temp!=null) return temp;
			else{
				boolean flag=false;
				for(int i=node.current-1; i>=0; i--){
					if(data.key>node.dArr[i].key){
						node=node.nArr[i+1];
						flag=true;
						break;
					}
				}
				if(flag==false) node=node.nArr[0];
			}
		}
		return null;
	}

	public void insert(DataItem data){
		Node node=root;
		Node prev=root;
		while(node!=null){
			if(node.current==3){
				if(node==root){
					split(node);
					node=root;
				}
				else{
					split(node);
					node=node.parent;
				}
			}
			else{
				boolean flag=false;
				prev=node;
				for(int i=node.current-1; i>=0; i--){
					if(data.key>=node.dArr[i].key){
						node=node.nArr[i+1];
						flag=true;
						break;
					}
				}
				if(flag==false) node=node.nArr[0];
			}
		}
		prev.insertItem(data);
	}

	public void split(Node node){
		if(node==root){
			Node newNode=new Node();
			Node newNode1=new Node();
			newNode.insertItem(node.removeItem(node.dArr[1]));
			newNode1.insertItem(node.removeItem(node.dArr[1]));
			newNode.nArr[0]=node;
			newNode.nArr[1]=newNode1;
			if(node.nArr[2]!=null) node.nArr[2].parent=newNode1;
			if(node.nArr[3]!=null) node.nArr[3].parent=newNode1;
			newNode1.nArr[0]=node.nArr[2];
			newNode1.nArr[1]=node.nArr[3];
			node.nArr[2]=null;
			node.nArr[3]=null;
			newNode1.parent=newNode;
			node.parent=newNode;
			root=newNode;
		}
		else{
			int ptr=0;
			while(node.parent.nArr[ptr]!=node){
				ptr++;
				if(ptr==4){
					node.parent.display();
					node.display();
					System.out.println("yes");
				}
			}
			Node newNode=new Node();
			for(int i=node.parent.current; i>ptr; i--) node.parent.nArr[i+1]=node.parent.nArr[i];
/*			if(node.parent.current==1 && ptr==0) node.parent.nArr[2]=node.parent.nArr[1];
			else if(node.parent.current==2 && ptr==0){
				node.parent.nArr[3]=node.parent.nArr[2];
				node.parent.nArr[2]=node.parent.nArr[1];
			}
			else if(node.parent.current==2 && ptr==1){
				node.parent.nArr[3]=node.parent.nArr[2];
			}*/
			node.parent.insertItem(node.removeItem(node.dArr[1]));
			newNode.insertItem(node.removeItem(node.dArr[1]));
			node.parent.nArr[ptr+1]=newNode;
			if(node.nArr[2]!=null) node.nArr[2].parent=newNode;
			if(node.nArr[3]!=null) node.nArr[3].parent=newNode;
			newNode.nArr[0]=node.nArr[2];
			newNode.nArr[1]=node.nArr[3];
			node.nArr[2]=null;
			node.nArr[3]=null;
			newNode.parent=node.parent;
		}
	}

	public void display(){
		displayNode(root);
	}

	private void displayNode(Node node){
		if(node==null) return;
		else{
			node.display();
			displayNode(node.nArr[0]);
			displayNode(node.nArr[1]);
			displayNode(node.nArr[2]);
			displayNode(node.nArr[3]);
		}
	}
}

class DataItem{
	public int key;

	public DataItem(){
		key=0;
	}
	
	public DataItem(int key){
		this.key=key;
	}

	public void display(){
		System.out.print("/"+key);
	}
}

class Node{
	public Node [] nArr;
	public DataItem [] dArr;
	public int current;
	public Node parent;
	public int counter;

	public Node(){
		nArr=new Node[4];
		for(int i=0; i<nArr.length; i++) nArr[i]=null;
		dArr=new DataItem[3];
		for(int i=0; i<dArr.length; i++) dArr[i]=new DataItem();
		current=0;
		parent=null;
		counter=0;
	}

	public DataItem findItem(DataItem data){
		for(int i=0; i<current; i++){
			if(dArr[i].key==data.key)
				return dArr[i];
		}
		return null;
	}

	public void insertItem(DataItem data){
		if(current==3){
			System.out.println("Full Node!");
		}
		else{
			int i;
			for(i=current-1; i>=0 && dArr[i].key>data.key; i--) dArr[i+1]=dArr[i];
			dArr[i+1]=data;
			current++;
		}
	}

	public DataItem removeItem(DataItem data){
		if(current==0){
			System.out.println("Empty Node!");
			return null;
		}
		else{
			int i=0;
			for(; i<current; i++){
				if(dArr[i].key==data.key)
					break;
			}
			if(i==current){
				System.out.println("Not Found!");
				return null;
			}
			else{
				DataItem temp=dArr[i];
				for(; i<current-1; i++)
					dArr[i]=dArr[i+1];
				current--;
				return temp;
			}
		}
	}

	public void display(){
		for(int i=0; i<current; i++){
			dArr[i].display();
	//		if(++counter==4){
	//			System.out.println();
	//			counter=0;
	//		}
		}
		System.out.println();
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值