树的遍历方式

树的遍历

(一)树结构实现

Java代码 复制代码
  1. package tree.tree;   
  2.   
  3. import java.util.Iterator;   
  4. import java.util.List;   
  5.   
  6. /**  
  7.  * 树节点抽象接口  
  8.  *   
  9.  * @author jzj  
  10.  * @data 2009-12-17  
  11.  */  
  12. public abstract class TreeNode implements Comparable {   
  13.   
  14.     //父节点   
  15.     private TreeNode pNode;   
  16.   
  17.     //数据域,节点编号,不能修改   
  18.     private int nodeId;   
  19.   
  20.     //数据域,节点名字,能修改   
  21.     private String nodeName;   
  22.   
  23.     //节点深度,根默认为0   
  24.     private int depth;   
  25.   
  26.     public TreeNode getPMenuComponent() {   
  27.         return pNode;   
  28.     }   
  29.   
  30.     public void setPMenuComponent(TreeNode menuComponent) {   
  31.         pNode = menuComponent;   
  32.     }   
  33.   
  34.     public int getNodeId() {   
  35.         return nodeId;   
  36.     }   
  37.   
  38.     public void setNodeId(int nodeId) {   
  39.         this.nodeId = nodeId;   
  40.     }   
  41.   
  42.     public String getNodeName() {   
  43.         return nodeName;   
  44.     }   
  45.   
  46.     public void setNodeName(String nodeName) {   
  47.         this.nodeName = nodeName;   
  48.     }   
  49.   
  50.     public int getDepth() {   
  51.         return depth;   
  52.     }   
  53.   
  54.     public void setDepth(int depth) {   
  55.         this.depth = depth;   
  56.     }   
  57.   
  58.     //添加子节点 默认不支持,叶子节点不支持此功能   
  59.     public void addSubNode(TreeNode menuComponent) {   
  60.         throw new UnsupportedOperationException();   
  61.     }   
  62.   
  63.     //删除子节点 默认不支持,叶子节点不支持此功能   
  64.     public void removeSubNode(TreeNode menuComponent) {   
  65.         throw new UnsupportedOperationException();   
  66.     }   
  67.   
  68.     //修改节点信息   
  69.     public void modiNodeInfo(String nodeName) {   
  70.         this.setNodeName(nodeName);   
  71.     }   
  72.   
  73.     //获取子节点 默认不支持,叶子节点不支持此功能   
  74.     public List getSubNodes() {   
  75.         throw new UnsupportedOperationException();   
  76.     }   
  77.   
  78.     //打印节点信息   
  79.     public void print() {   
  80.         throw new UnsupportedOperationException();   
  81.     }   
  82.   
  83.     //获取节点信息   
  84.     protected abstract StringBuffer getNodeInfo();   
  85.   
  86.     //提供深度迭代器 默认不支持,叶子节点不支持此功能   
  87.     public Iterator createDepthOrderIterator() {   
  88.         throw new UnsupportedOperationException();   
  89.     }   
  90.   
  91.     //提供广度优先迭代器 默认不支持,叶子节点不支持此功能   
  92.     public Iterator createLayerOrderIterator() {   
  93.         throw new UnsupportedOperationException();   
  94.     }   
  95.   
  96.     /**  
  97.      * 根据树节点id,在当然节点与子节点中搜索指定的节点  
  98.      * @param treeId  
  99.      * @return TreeNode  
  100.      */  
  101.     public TreeNode getTreeNode(int treeId) {   
  102.         return getNode(this, treeId);   
  103.     }   
  104.   
  105.     /**  
  106.      * 使用树的先序遍历递归方式查找指定的节点  
  107.      *   
  108.      * @param treeNode 查找的起始节点  
  109.      * @param treeId 节点编号  
  110.      * @return  
  111.      */  
  112.     protected TreeNode getNode(TreeNode treeNode, int treeId) {   
  113.         throw new UnsupportedOperationException();   
  114.     }   
  115.   
  116.     public int compareTo(Object o) {   
  117.   
  118.         TreeNode temp = (TreeNode) o;   
  119.   
  120.         return this.getNodeId() > temp.getNodeId() ? 1 : (this.getNodeId() < temp   
  121.                 .getNodeId() ? -1 : 0);   
  122.     }   
  123.   
  124.     public boolean equals(Object menuComponent) {   
  125.   
  126.         if (!(menuComponent instanceof TreeNode)) {   
  127.             return false;   
  128.         }   
  129.         TreeNode menu = (TreeNode) menuComponent;   
  130.   
  131.         // 如果两个节点的nodeID相应则认为是同一节点   
  132.         return this.getNodeId() == menu.getNodeId();   
  133.     }   
  134. }  
package tree.tree;

import java.util.Iterator;
import java.util.List;

/**
 * 树节点抽象接口
 * 
 * @author jzj
 * @data 2009-12-17
 */
public abstract class TreeNode implements Comparable {

	//父节点
	private TreeNode pNode;

	//数据域,节点编号,不能修改
	private int nodeId;

	//数据域,节点名字,能修改
	private String nodeName;

	//节点深度,根默认为0
	private int depth;

	public TreeNode getPMenuComponent() {
		return pNode;
	}

	public void setPMenuComponent(TreeNode menuComponent) {
		pNode = menuComponent;
	}

	public int getNodeId() {
		return nodeId;
	}

	public void setNodeId(int nodeId) {
		this.nodeId = nodeId;
	}

	public String getNodeName() {
		return nodeName;
	}

	public void setNodeName(String nodeName) {
		this.nodeName = nodeName;
	}

	public int getDepth() {
		return depth;
	}

	public void setDepth(int depth) {
		this.depth = depth;
	}

	//添加子节点 默认不支持,叶子节点不支持此功能
	public void addSubNode(TreeNode menuComponent) {
		throw new UnsupportedOperationException();
	}

	//删除子节点 默认不支持,叶子节点不支持此功能
	public void removeSubNode(TreeNode menuComponent) {
		throw new UnsupportedOperationException();
	}

	//修改节点信息
	public void modiNodeInfo(String nodeName) {
		this.setNodeName(nodeName);
	}

	//获取子节点 默认不支持,叶子节点不支持此功能
	public List getSubNodes() {
		throw new UnsupportedOperationException();
	}

	//打印节点信息
	public void print() {
		throw new UnsupportedOperationException();
	}

	//获取节点信息
	protected abstract StringBuffer getNodeInfo();

	//提供深度迭代器 默认不支持,叶子节点不支持此功能
	public Iterator createDepthOrderIterator() {
		throw new UnsupportedOperationException();
	}

	//提供广度优先迭代器 默认不支持,叶子节点不支持此功能
	public Iterator createLayerOrderIterator() {
		throw new UnsupportedOperationException();
	}

	/**
	 * 根据树节点id,在当然节点与子节点中搜索指定的节点
	 * @param treeId
	 * @return TreeNode
	 */
	public TreeNode getTreeNode(int treeId) {
		return getNode(this, treeId);
	}

	/**
	 * 使用树的先序遍历递归方式查找指定的节点
	 * 
	 * @param treeNode 查找的起始节点
	 * @param treeId 节点编号
	 * @return
	 */
	protected TreeNode getNode(TreeNode treeNode, int treeId) {
		throw new UnsupportedOperationException();
	}

	public int compareTo(Object o) {

		TreeNode temp = (TreeNode) o;

		return this.getNodeId() > temp.getNodeId() ? 1 : (this.getNodeId() < temp
				.getNodeId() ? -1 : 0);
	}

	public boolean equals(Object menuComponent) {

		if (!(menuComponent instanceof TreeNode)) {
			return false;
		}
		TreeNode menu = (TreeNode) menuComponent;

		// 如果两个节点的nodeID相应则认为是同一节点
		return this.getNodeId() == menu.getNodeId();
	}
}

   

Java代码 复制代码
  1. package tree.tree;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Iterator;   
  5. import java.util.List;   
  6.   
  7. /**  
  8.  * 树的分支节点  
  9.  *  
  10.  * @author jzj  
  11.  * @data 2009-12-17  
  12.  */  
  13. public class TreeBranchNode extends TreeNode {   
  14.   
  15.     //存储子节点   
  16.     List subNodesList = new ArrayList();   
  17.   
  18.     public TreeBranchNode(int nodeId, String nodeName) {   
  19.         this.setNodeId(nodeId);   
  20.         this.setNodeName(nodeName);   
  21.     }   
  22.   
  23.     //添加子节点   
  24.     public void addSubNode(TreeNode menuComponent) {   
  25.         // 设置父节点   
  26.         menuComponent.setPMenuComponent(this);   
  27.   
  28.         // 设置节点的深度   
  29.         menuComponent.setDepth(this.getDepth() + 1);   
  30.         subNodesList.add(menuComponent);   
  31.     }   
  32.   
  33.     //删除一个子节点   
  34.     public void removeSubNode(TreeNode menuComponent) {   
  35.         subNodesList.remove(menuComponent);   
  36.     }   
  37.   
  38.     //获取子节点   
  39.     public List getSubNodes() {   
  40.         return subNodesList;   
  41.     }   
  42.   
  43.     //打印节点信息,以树的形式展示,所以它包括了所有子节点信息   
  44.     public void print() {   
  45.         System.out.println(this.getNodeInfo());   
  46.     }   
  47.   
  48.     //打印节点本身信息,不递归打印子节点信息   
  49.     public String toString() {   
  50.         return getSefNodeInfo().toString();   
  51.     }   
  52.   
  53.     // 递归打印节点信息实现   
  54.     protected StringBuffer getNodeInfo() {   
  55.   
  56.         StringBuffer sb = getSefNodeInfo();   
  57.         sb.append(System.getProperty("line.separator"));   
  58.         //如果有子节点   
  59.         for (Iterator iter = subNodesList.iterator(); iter.hasNext();) {   
  60.             TreeNode node = (TreeNode) iter.next();   
  61.             //递归打印子节点信息   
  62.             sb.append(node.getNodeInfo());   
  63.   
  64.             if (iter.hasNext()) {   
  65.                 sb.append(System.getProperty("line.separator"));   
  66.             }   
  67.   
  68.         }   
  69.         return sb;   
  70.     }   
  71.   
  72.     //节点本身信息,不含子节点信息   
  73.     private StringBuffer getSefNodeInfo() {   
  74.         StringBuffer sb = new StringBuffer();   
  75.   
  76.         // 打印缩进   
  77.         for (int i = 0; i < this.getDepth(); i++) {   
  78.             sb.append(' ');   
  79.         }   
  80.         sb.append("+--");   
  81.   
  82.         sb.append("[nodeId=");   
  83.         sb.append(this.getNodeId());   
  84.         sb.append(" nodeName=");   
  85.   
  86.         sb.append(this.getNodeName());   
  87.         sb.append(']');   
  88.         return sb;   
  89.     }   
  90.   
  91.     //为外界提供遍历组合结构的迭代器   
  92.     public Iterator createDepthOrderIterator() {   
  93.         return new TreeOutOrder.DepthOrderIterator(this);   
  94.     }   
  95.   
  96.     //为外界提供遍历组合结构的迭代器   
  97.     public Iterator createLayerOrderIterator() {   
  98.         return new TreeOutOrder.LevelOrderIterator(this);   
  99.     }   
  100.   
  101.     /**  
  102.      * 使用树的先序遍历递归方式查找指定的节点  
  103.      *   
  104.      * @param treeNode 查找的起始节点  
  105.      * @param treeId 节点编号  
  106.      * @return  
  107.      */  
  108.     protected TreeNode getNode(TreeNode treeNode, int treeId) {   
  109.   
  110.         //如果找到,则停止后续搜索,并把查找到的节点返回给上层调用者   
  111.         if (treeNode.getNodeId() == treeId) {//1、先与父节点比对   
  112.             return treeNode;   
  113.         }   
  114.   
  115.         TreeNode tmp = null;   
  116.   
  117.         //如果为分支节点,则遍历子节点   
  118.         if (treeNode instanceof TreeBranchNode) {   
  119.   
  120.             for (int i = 0; i < treeNode.getSubNodes().size(); i++) {//2、再与子节点比对   
  121.                 tmp = getNode((TreeNode) treeNode.getSubNodes().get(i), treeId);   
  122.                 if (tmp != null) {//如果查找到,则返回上层调用者   
  123.                     return tmp;   
  124.                 }   
  125.             }   
  126.         }   
  127.   
  128.         //如果没有找到,返回上层调用者   
  129.         return null;   
  130.     }   
  131. }  
package tree.tree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 树的分支节点
 *
 * @author jzj
 * @data 2009-12-17
 */
public class TreeBranchNode extends TreeNode {

	//存储子节点
	List subNodesList = new ArrayList();

	public TreeBranchNode(int nodeId, String nodeName) {
		this.setNodeId(nodeId);
		this.setNodeName(nodeName);
	}

	//添加子节点
	public void addSubNode(TreeNode menuComponent) {
		// 设置父节点
		menuComponent.setPMenuComponent(this);

		// 设置节点的深度
		menuComponent.setDepth(this.getDepth() + 1);
		subNodesList.add(menuComponent);
	}

	//删除一个子节点
	public void removeSubNode(TreeNode menuComponent) {
		subNodesList.remove(menuComponent);
	}

	//获取子节点
	public List getSubNodes() {
		return subNodesList;
	}

	//打印节点信息,以树的形式展示,所以它包括了所有子节点信息
	public void print() {
		System.out.println(this.getNodeInfo());
	}

	//打印节点本身信息,不递归打印子节点信息
	public String toString() {
		return getSefNodeInfo().toString();
	}

	// 递归打印节点信息实现
	protected StringBuffer getNodeInfo() {

		StringBuffer sb = getSefNodeInfo();
		sb.append(System.getProperty("line.separator"));
		//如果有子节点
		for (Iterator iter = subNodesList.iterator(); iter.hasNext();) {
			TreeNode node = (TreeNode) iter.next();
			//递归打印子节点信息
			sb.append(node.getNodeInfo());

			if (iter.hasNext()) {
				sb.append(System.getProperty("line.separator"));
			}

		}
		return sb;
	}

	//节点本身信息,不含子节点信息
	private StringBuffer getSefNodeInfo() {
		StringBuffer sb = new StringBuffer();

		// 打印缩进
		for (int i = 0; i < this.getDepth(); i++) {
			sb.append(' ');
		}
		sb.append("+--");

		sb.append("[nodeId=");
		sb.append(this.getNodeId());
		sb.append(" nodeName=");

		sb.append(this.getNodeName());
		sb.append(']');
		return sb;
	}

	//为外界提供遍历组合结构的迭代器
	public Iterator createDepthOrderIterator() {
		return new TreeOutOrder.DepthOrderIterator(this);
	}

	//为外界提供遍历组合结构的迭代器
	public Iterator createLayerOrderIterator() {
		return new TreeOutOrder.LevelOrderIterator(this);
	}

	/**
	 * 使用树的先序遍历递归方式查找指定的节点
	 * 
	 * @param treeNode 查找的起始节点
	 * @param treeId 节点编号
	 * @return
	 */
	protected TreeNode getNode(TreeNode treeNode, int treeId) {

		//如果找到,则停止后续搜索,并把查找到的节点返回给上层调用者
		if (treeNode.getNodeId() == treeId) {//1、先与父节点比对
			return treeNode;
		}

		TreeNode tmp = null;

		//如果为分支节点,则遍历子节点
		if (treeNode instanceof TreeBranchNode) {

			for (int i = 0; i < treeNode.getSubNodes().size(); i++) {//2、再与子节点比对
				tmp = getNode((TreeNode) treeNode.getSubNodes().get(i), treeId);
				if (tmp != null) {//如果查找到,则返回上层调用者
					return tmp;
				}
			}
		}

		//如果没有找到,返回上层调用者
		return null;
	}
}

 

Java代码 复制代码
  1. package tree.tree;   
  2.   
  3. /**  
  4.  * 树的叶子节点  
  5.  *  
  6.  * @author jzj  
  7.  * @data 2009-12-17  
  8.  *  
  9.  */  
  10. public class TreeLeafNode extends TreeNode {   
  11.     public TreeLeafNode(int nodeId, String nodeName) {   
  12.         this.setNodeId(nodeId);   
  13.         this.setNodeName(nodeName);   
  14.     }   
  15.   
  16.     // 获取叶子节点信息   
  17.     protected StringBuffer getNodeInfo() {   
  18.         StringBuffer sb = new StringBuffer();   
  19.   
  20.         // 打印缩进   
  21.         for (int i = 0; i < this.getDepth(); i++) {   
  22.             sb.append(' ');   
  23.         }   
  24.         sb.append("---");   
  25.   
  26.         sb.append("[nodeId=");   
  27.         sb.append(this.getNodeId());   
  28.         sb.append(" nodeName=");   
  29.   
  30.         sb.append(this.getNodeName());   
  31.         sb.append(']');   
  32.   
  33.         return sb;   
  34.     }   
  35.   
  36.     public String toString() {   
  37.         return getNodeInfo().toString();   
  38.     }   
  39. }   
package tree.tree;

/**
 * 树的叶子节点
 *
 * @author jzj
 * @data 2009-12-17
 *
 */
public class TreeLeafNode extends TreeNode {
	public TreeLeafNode(int nodeId, String nodeName) {
		this.setNodeId(nodeId);
		this.setNodeName(nodeName);
	}

	// 获取叶子节点信息
	protected StringBuffer getNodeInfo() {
		StringBuffer sb = new StringBuffer();

		// 打印缩进
		for (int i = 0; i < this.getDepth(); i++) {
			sb.append(' ');
		}
		sb.append("---");

		sb.append("[nodeId=");
		sb.append(this.getNodeId());
		sb.append(" nodeName=");

		sb.append(this.getNodeName());
		sb.append(']');

		return sb;
	}

	public String toString() {
		return getNodeInfo().toString();
	}
} 

(二)利用树本身特点进行递归遍历(属内部遍历)

树的内部遍历方式有两种:前序遍历、后序遍历,注,没有中序遍历。与二叉树的内部遍历方式一样也是采用递归方式实现的。

Java代码 复制代码
  1. package tree.tree;   
  2.   
  3. /**  
  4.  * 树的两种 内部 遍历方式:前序遍历、后序遍历  
  5.  *   
  6.  * @author jzj  
  7.  * @data 2009-12-17  
  8.  */  
  9. public class TreeInOrder {   
  10.   
  11.     /**  
  12.      * 树的前序递归遍历 pre=prefix(前缀)  
  13.      * @param node 要遍历的节点  
  14.      */  
  15.     public static void preOrder(TreeNode node) {   
  16.         //如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null   
  17.         if (node != null) {   
  18.             System.out.print(node.getNodeId() + " ");//先遍历父节点   
  19.   
  20.             if (node instanceof TreeBranchNode) {   
  21.                 for (int i = 0; i < node.getSubNodes().size(); i++) {   
  22.                     preOrder((TreeNode) node.getSubNodes().get(i));//再遍历子节点   
  23.                 }   
  24.             }   
  25.   
  26.         }   
  27.     }   
  28.   
  29.     /**  
  30.      * 树的后序递归遍历 post=postfix(后缀)  
  31.      * @param node 要遍历的节点  
  32.      */  
  33.     public static void postOrder(TreeNode node) {   
  34.         //如果传进来的节点不为空,则遍历   
  35.         if (node != null) {   
  36.             //如果为分支节点,则遍历子节点   
  37.             if (node instanceof TreeBranchNode) {   
  38.   
  39.                 for (int i = 0; i < node.getSubNodes().size(); i++) {   
  40.                     postOrder((TreeNode) node.getSubNodes().get(i));//先遍历子节点   
  41.                 }   
  42.             }   
  43.             System.out.print(node.getNodeId() + " ");//后遍历父节点   
  44.         }   
  45.     }   
  46. }   
package tree.tree;

/**
 * 树的两种 内部 遍历方式:前序遍历、后序遍历
 * 
 * @author jzj
 * @data 2009-12-17
 */
public class TreeInOrder {

	/**
	 * 树的前序递归遍历 pre=prefix(前缀)
	 * @param node 要遍历的节点
	 */
	public static void preOrder(TreeNode node) {
		//如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null
		if (node != null) {
			System.out.print(node.getNodeId() + " ");//先遍历父节点

			if (node instanceof TreeBranchNode) {
				for (int i = 0; i < node.getSubNodes().size(); i++) {
					preOrder((TreeNode) node.getSubNodes().get(i));//再遍历子节点
				}
			}

		}
	}

	/**
	 * 树的后序递归遍历 post=postfix(后缀)
	 * @param node 要遍历的节点
	 */
	public static void postOrder(TreeNode node) {
		//如果传进来的节点不为空,则遍历
		if (node != null) {
			//如果为分支节点,则遍历子节点
			if (node instanceof TreeBranchNode) {

				for (int i = 0; i < node.getSubNodes().size(); i++) {
					postOrder((TreeNode) node.getSubNodes().get(i));//先遍历子节点
				}
			}
			System.out.print(node.getNodeId() + " ");//后遍历父节点
		}
	}
} 

(三)利用栈与队列对树进行非递归遍历(属外部遍历)

树的两种外部非递归遍历方式:深度优先(即先根)遍历、广度优先(即层次)遍历。它们需借助于栈与队列来实现。

Java代码 复制代码
  1. package tree.tree;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Iterator;   
  5. import java.util.Stack;   
  6.   
  7. import queue.LinkedQueue;   
  8.   
  9. public class TreeOutOrder {   
  10.     /**  
  11.      * 深度优先遍历迭代器  
  12.      *   
  13.      * @author jzj  
  14.      * @data 2009-12-17  
  15.      */  
  16.     public static class DepthOrderIterator implements Iterator {   
  17.         //栈,用来深度遍历树节点,以便回溯   
  18.         Stack stack = new Stack();   
  19.   
  20.         public DepthOrderIterator(TreeNode rootNode) {   
  21.             ArrayList list = new ArrayList();   
  22.             list.add(rootNode);   
  23.   
  24.             // 将根节点迭代器入栈   
  25.             stack.push(list.iterator());   
  26.         }   
  27.   
  28.         //是否有下一元素   
  29.         public boolean hasNext() {   
  30.             // 如果栈为空则返回,证明没有可遍历的元素   
  31.             if (stack.empty()) {   
  32.                 return false;   
  33.             } else {   
  34.                 // 如果栈不为空,则取出栈顶元素(迭代器)   
  35.                 Iterator iterator = (Iterator) stack.peek();   
  36.   
  37.                 // 这里使用简单元素(即线性排列的元素,而不是树状结构的元素)的方式来遍历   
  38.                 if (!iterator.hasNext()) {   
  39.                     // 如果取出迭代器已经遍历完成,则弹出迭代器,以便回退到上一(父)迭代器继续开妈以深度优先方式遍历   
  40.                     stack.pop();   
  41.   
  42.                     // 通过递归方式继续遍历父迭代器还未遍历到的节点元素   
  43.                     return hasNext();   
  44.                 } else {   
  45.                     // 如果找到了下一个元素,返回true   
  46.                     return true;   
  47.                 }   
  48.             }   
  49.         }   
  50.   
  51.         // 取下一元素   
  52.         public Object next() {   
  53.             // 如果还有下一个元素,则先取到该元素所对应的迭代器引用,以便取得该节点元素   
  54.             if (hasNext()) {   
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值