树的双亲表示法

树的双亲表示法是用一组连续空间(数组)存储树的节点,同时在每个节点中附设一个指示器指示其双亲节点在数组中的位置。

其结构如图:

package tree;

import java.util.*;
public class PTree<AnyType> {
	 int max=100;
	 int n,root;
	 int a[]=new int[max];     //用于存放孩子结点在数组中的位置
	 PTNode nodes[]=new PTNode[max];
	 
     class PTNode<AnyType>{
   	      AnyType data;
   	      int parent;
   	      public PTNode(AnyType d,int p){
   		      this.data=d;
   		      this.parent=p; 
   	 }
    }
     public PTree(){
    	 n=0;
     }
     public boolean isEmpty(){               //判断是否为空
    	 return n==0;
     }
     
     public PTNode assign(AnyType d,int p){       //给结点赋值
   	    PTNode newNode=new PTNode(d,p);
   	    return newNode;
    }
     
     public void insert(AnyType d,int p){         //添加新结点,给定结点位置
    	   nodes[n]=assign(d,p);
    	   n++;
     }
     public void insert(PTree tree,int p){           //添加子树,给定结点位置
    	 int m=n;                                   //m为tree非根结点双亲位置的增加值
    	 AnyType value=(AnyType)tree.getRoot();
    	 insert(value,p);
    	 for(int i=1;i<tree.n;i++){
    		 AnyType x=(AnyType)tree.getData(i);
    		 insert(x,tree.nodes[i].parent+m);               //将tree的非根结点的双亲位置都加m后添加到另一个树中
    	 }
     }
     public void insert(PTree tree,AnyType d){        //添加子树,给定结点data
    	 int idx=0;
    	 for(int i=0;i<n;i++){
    		 int x=((String)(nodes[i].data)).compareTo((String)d);
    		 if(x==0)
    			 idx=i;
    	 }
    	 int m=n;                                   //m为tree非根结点双亲位置的增加值
    	 AnyType value=(AnyType)tree.getRoot();
    	 insert(value,idx);
    	 for(int i=1;i<tree.n;i++){
    		 AnyType x=(AnyType)tree.getData(i);
    		 insert(x,tree.nodes[i].parent+m);               //将tree的非根结点的双亲位置都加m后添加到另一个树中
    	 }

     }
     
     
     public void delete(int p){
    	
    	 if(p>n)
    		 System.out.println("数据不存在");
    	 else if(getChildCount(p)==0){        //叶子
    		 if(p==(n-1)){                    //数组的最后一个
    			 nodes[p].data=null;
    		     nodes[p].parent=-2;
    		 }
    		int k;
    		for(k=p+1;k<n;k++){
    			nodes[k-1]=nodes[k];          //令被删除的结点后面的结点向前平移
    			if(nodes[k].parent>p)
    				nodes[k].parent--;
    		}
    		n--;
    	 }
    	 else{
    		 int dep=getDepth(p);
    		 int num[]=new int[n];
    		 num[0]=p;
    		 int count=1,par=0;
    		 for(int i=0;i<n;i++){
    			 int d=getDepth(i);
    			  par=nodes[i].parent;
    			 while(par!=-1){
    				 if(par==p){
    					num[count]=i; 
    					count++;
    					break;
    				 }
    				 par=nodes[par].parent;
    				 d--;
    			 }
    			 
    		 }
    		 AnyType a[]=(AnyType[])new Object[count]; 
    		 for(int i=0;i<count;i++){
    			 a[i]=(AnyType)nodes[num[i]].data;
    		 }/*
    		 System.out.println(a.length);
    		 for(int i=0;i<count;i++){
    			 System.out.println(a[i]);
    		 }*/
    		 int j;
    		 for(j=0;j<n;j++){
    			 for(int x=0;x<a.length;x++){
    				 int y=((String)nodes[j].data).compareTo((String)a[x]);
    				 if(y==0){
    					 int b;
    					 for(b=j+1;b<n;b++) {
    						 nodes[b-1]=nodes[b];
    						 if(nodes[b].parent>j){
    							 nodes[b-1].parent--;
    						 }	    
    					 } 
    					
    					 j--;
    					 n--;
    				 }
    				  
    			 }
    		 }    		
    		 }
    	 }
    	 
    	 
     
     public AnyType getRoot(){    //返回根结点元素,根结点不一定存在数组中第一个位置
    	 for(int i=0;i<n;i++){
    		 if(nodes[i].parent==-1)
    			 return (AnyType)nodes[i].data;
    	 }
    	return null;
     }
     
     public AnyType getData(int i){             //返回序号为i的结点的数据
    	 if(i>n){
    		 return null;
    	 }
    	 return (AnyType)nodes[i].data;
     }
  
     
     public PTNode getParent(int p){            //返回父母结点,给定该结点位置
    	  int pare=nodes[p].parent;
    	  return nodes[pare];
     }
     public PTNode getParent(AnyType d){            //返回父母结点,给定该结点data
    	 int p=0;
    	 for(int i=0;i<n;i++){
    		 int x=((String)(nodes[i].data)).compareTo((String)d);
    		 if(x==0)
    			 p=i;
    	 }
    	 
   	  int pare=nodes[p].parent;
   	  return nodes[pare];
    }
     
     
     public AnyType getParentData(int p){       //返回父母结点元素
    	 if(p>n){
    		 return null;
    	 }
    	   return (AnyType)getParent(p).data;
     }
     
     public int getChildCount(int p){            //返回孩子结点数
    	 int count=0;    	 
    	 for(int i=0;i<n;i++){
    		 if(nodes[i].parent==p){
    			 a[count]=i;                     //将该结点的孩子结点在数组中的位置存下来
    			 count++;
    		 }
    	 }
    	 return count;
     }
     
     public int getChildCount(AnyType d){            //返回孩子结点数,给定结点值
    	 int p=0;
    	 for(int i=0;i<n;i++){
    		 int x=((String)(nodes[i].data)).compareTo((String)d);
    		 if(x==0)
    			 p=i;
    	 }
    	 int count=0;    	 
    	 for(int i=0;i<n;i++){
    		 if(nodes[i].parent==p){
    			 a[count]=i;                     //将该结点的孩子结点在数组中的位置存下来
    			 count++;
    		 }
    	 }
    	 return count;
     }
     
     
     public PTNode getFirstChild(int p){         //获得第一个孩子结点
    	 int c=getChildCount(p);                //得到孩子结点个数
    	 PTNode kong=new PTNode(null,-2);
    	 if(c==0){
    		 return kong;
    	 }
    	 else{
    		 return nodes[a[0]];
    	 }	 
     }
     public PTNode getNextChild(int p){
    	 PTNode kong=new PTNode(null,-2);
        int c=getChildCount(nodes[p].parent);         //执行求该结点的双亲结点的孩子结点的个数的方法,以获得保存其兄弟结点在数组中的位置的数组及孩子个数
    	 int next=0;
    	 for(int i=0;i<c;i++){
    		 if(a[i]==p){
    			 if(i+1<c){              //判断p是否有下一个兄弟结点
    			      next=a[i+1];             //若有,获得p的兄弟结点的位置 ,跳出循环
    			      break;
    			   }
    			 else
    				 return kong;           //没有,返回null
    		 }	
    	 }
			 return nodes[next];                //返回兄弟结点
    	   
     }
     
     
     public int depth(){
    	int max=0,height,p=0;//max记录当前的最大高度,p记录双亲结点的位置,height为当前的深度
    	for(int i=0;i<n;i++){
    		height=1;               //每次循环开始,初始化height
    		p=nodes[i].parent;
    		while(p!=-1){         //若当前结点不是根结点,执行此循环
     			p=nodes[p].parent;      //不断沿双亲结点向上走
     			height++;               //没向上一步,高度加一
    		}
    		if(height>max)           //记录当前最大深度
    			max=height;
    	}
    	return max;
     }
     public int getDepth(int m){               //获得某一结点所处的层次
    	 if(m>n)
    		 return -2;
    	 int max=0,height,p=0;
    	 for(int i=0;i<n;i++){
     		height=1;               //每次循环开始,初始化height
     		p=nodes[m].parent;
     		while(p!=-1){         //若当前结点不是根结点,执行此循环
      			p=nodes[p].parent;      //不断沿双亲结点向上走
      			height++;               //没向上一步,高度加一
     		}
     		if(height>max)           //记录当前最大深度
     			max=height;
     	}
     	return max;
     }
    
	public static void main(String[] args) {
           PTree pt=new PTree();
           PTree tr=new PTree();
           pt.insert("aaa",-1);
           pt.insert("bbb",0);
           pt.insert("ccc",0);
           pt.insert("ddd",1);
           pt.insert("eee",2);
           pt.insert("fff",2);
           pt.insert("ggg",4);
           tr.insert("A",-1);tr.insert("B",0);tr.insert("C",0);
           pt.insert(tr,"ddd");
           for(int i=0;i<10;i++){
         	  System.out.println( pt.getData(i));  
           }
           System.out.println("******************");
           System.out.println( pt.n);
           System.out.println("******************");
           System.out.println( pt.getRoot());
           System.out.println("******************");
           System.out.println( pt.getParent("fff").data);
           System.out.println("******************");
           System.out.println( pt.getDepth(9));
           System.out.println("******************"); 
           System.out.println(pt.getFirstChild(3).data);  
           System.out.println("******************");
           pt.delete(1);
           System.out.println( pt.n);
           System.out.println( pt.n);
           for(int i=0;i<pt.n;i++){
             System.out.println( pt.getData(i));  
           }
	}

}


 

原文地址:https://www.cnblogs.com/oversea201405/p/3752269.html