JAVA多叉树森林的构造、内存存储、磁盘存储与层序、先序(深度)遍历

   因为项目需要简历一个森林来保存图形之间的父子关系,因此建立一种多叉树作为验证模型。具体原理如下草稿所示:





实现代码如下:

结点数据结构:

package com.test.forest;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class SerPath implements Serializable{
	
	private int fakePath = 0;
	
	public int layerIndex = -1;
	
	public List<SerPath> childList = new ArrayList<>();
	
	public SerPath(int index){
		fakePath = index;
	}
	
	public int getPath(){
		return fakePath;
	}
}

遍历流程:

package com.test.forest;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

public class Forest {
	
	/**构造测试样本**/
	public List<SerPath> createForest() {
		/**森林表**/
		List<SerPath> forestTreeHeadList = new ArrayList<>();
		/**第一棵树**/
		SerPath treeHead1 = new SerPath(1);
		treeHead1.childList.add(new SerPath(2));
		treeHead1.childList.add(new SerPath(3));
		treeHead1.childList.add(new SerPath(4));
		treeHead1.childList.add(new SerPath(5));
		treeHead1.childList.get(2).childList.add(new SerPath(6));
		treeHead1.childList.get(2).childList.add(new SerPath(7));
		treeHead1.childList.get(2).childList.add(new SerPath(8));
		treeHead1.childList.get(2).childList.add(new SerPath(9));
		forestTreeHeadList.add(treeHead1);
		/**第2棵树**/
		SerPath treeHead2 = new SerPath(10);
		treeHead2.childList.add(new SerPath(11));
		treeHead2.childList.add(new SerPath(12));
		treeHead2.childList.add(new SerPath(13));
		treeHead2.childList.get(0).childList.add(new SerPath(14));
		treeHead2.childList.get(0).childList.add(new SerPath(15));
		treeHead2.childList.get(0).childList.add(new SerPath(16));
		treeHead2.childList.get(2).childList.add(new SerPath(17));
		treeHead2.childList.get(2).childList.add(new SerPath(18));
		forestTreeHeadList.add(treeHead2);
		return forestTreeHeadList;
	}
	
	/**遍历森林中的所有树和树节点**/
	public void readForest(List<SerPath> forestTreeHeadList) {
		for(SerPath treeHead : forestTreeHeadList){
			Queue<List<SerPath>> layerQueue = new LinkedBlockingQueue<>();
			//输出头结点的值:
			System.out.println(treeHead.getPath());
			//发现头结点有孩子表,表入队:
			if(!treeHead.childList.isEmpty()){ 
				layerQueue.add(treeHead.childList);
			}
			//只要孩子表队列不为空就循环
			while(!layerQueue.isEmpty()){
				List<SerPath> nodeList = layerQueue.poll(); //出队孩子表表头
				for(SerPath childNode : nodeList){   //遍历当前孩子表,如果孩子节点也有孩子表,则将这个孩子节点的孩子表放入队尾等候遍历
					System.out.println(childNode.getPath());  //读孩子数据
					if(!childNode.childList.isEmpty()) {  //如果孩子节点也有孩子表,则将这个孩子节点的孩子表放入队尾等候遍历
						layerQueue.add(childNode.childList);
					}
				}
			}
		}
	}
	
	
	
	
	public static void main(String[] args) {
		Forest forest = new Forest();
		forest.readForest(forest.createForest());
	}

}


实际输出:



利用序列化保存再读取的测试:

package com.test.forest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

public class Forest {
	
	/**构造测试样本**/
	public List<SerPath> createForest() {
		/**森林表**/
		List<SerPath> forestTreeHeadList = new ArrayList<>();
		/**第一棵树**/
		SerPath treeHead1 = new SerPath(1);
		treeHead1.childList.add(new SerPath(2));
		treeHead1.childList.add(new SerPath(3));
		treeHead1.childList.add(new SerPath(4));
		treeHead1.childList.add(new SerPath(5));
		treeHead1.childList.get(2).childList.add(new SerPath(6));
		treeHead1.childList.get(2).childList.add(new SerPath(7));
		treeHead1.childList.get(2).childList.add(new SerPath(8));
		treeHead1.childList.get(2).childList.add(new SerPath(9));
		forestTreeHeadList.add(treeHead1);
		/**第2棵树**/
		SerPath treeHead2 = new SerPath(10);
		treeHead2.childList.add(new SerPath(11));
		treeHead2.childList.add(new SerPath(12));
		treeHead2.childList.add(new SerPath(13));
		treeHead2.childList.get(0).childList.add(new SerPath(14));
		treeHead2.childList.get(0).childList.add(new SerPath(15));
		treeHead2.childList.get(0).childList.add(new SerPath(16));
		treeHead2.childList.get(2).childList.add(new SerPath(17));
		treeHead2.childList.get(2).childList.add(new SerPath(18));
		forestTreeHeadList.add(treeHead2);
		return forestTreeHeadList;
	}
	
	/**遍历森林中的所有树和树节点**/
	public void readForest(List<SerPath> forestTreeHeadList) {
		for(SerPath treeHead : forestTreeHeadList){
			Queue<List<SerPath>> layerQueue = new LinkedBlockingQueue<>();
			//输出头结点的值:
			System.out.println(treeHead.getPath());
			//发现头结点有孩子表,表入队:
			if(!treeHead.childList.isEmpty()){ 
				layerQueue.add(treeHead.childList);
			}
			//只要孩子表队列不为空就循环
			while(!layerQueue.isEmpty()){
				List<SerPath> nodeList = layerQueue.poll(); //出队孩子表表头
				for(SerPath childNode : nodeList){   //遍历当前孩子表,如果孩子节点也有孩子表,则将这个孩子节点的孩子表放入队尾等候遍历
					System.out.println(childNode.getPath());  //读孩子数据
					if(!childNode.childList.isEmpty()) {  //如果孩子节点也有孩子表,则将这个孩子节点的孩子表放入队尾等候遍历
						layerQueue.add(childNode.childList);
					}
				}
			}
			
		}
	}
	
	
	/**前序遍历、深度优先遍历**/
	public void readForestDepthFirst(List<SerPath> forestTreeHeadList){
		if(forestTreeHeadList == null || forestTreeHeadList.isEmpty())
			return;
		for(SerPath path : forestTreeHeadList) {
			System.out.println(path.getPath());
			readForest(path.childList);
		}
	}
	
	
	
	
	public static void main(String[] args) {
		Forest forest = new Forest();
		List<SerPath> forestTreeHeadList = forest.createForest();
		//广度遍历:
		forest.readForest(forestTreeHeadList);
		
		System.out.println();
		
		try {
			File file = new File("E:\\1.temp");
			if(!file.exists()){
				file.createNewFile();
			}
			FileOutputStream outputStream = new FileOutputStream(file);
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
			objectOutputStream.writeObject(forestTreeHeadList);
			
			FileInputStream inputStream = new FileInputStream(file);
			ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
			List<SerPath> reLoad = (List<SerPath>) objectInputStream.readObject();
			
			//读取之后广度遍历第二次:
			forest.readForest(reLoad);
			
			//读取之后深度遍历:
			System.out.println();
			forest.readForestDepthFirst(reLoad);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
	}

}

测试结果:



猜你喜欢

转载自blog.csdn.net/cjzjolly/article/details/80742427