树的双亲表示法
树的双亲表示法是用一组连续空间(数组)存储树的节点,同时在每个节点中附设一个指示器指示其双亲节点在数组中的位置。
其结构如图:
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)); } } }