树的遍历
(一)树结构实现
- 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();
- }
- }
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();
}
}
- 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;
- }
- }
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;
}
}
- 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();
- }
- }
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();
}
}
(二)利用树本身特点进行递归遍历(属内部遍历)
树的内部遍历方式有两种:前序遍历、后序遍历,注,没有中序遍历。与二叉树的内部遍历方式一样也是采用递归方式实现的。
- 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() + " ");//后遍历父节点
- }
- }
- }
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() + " ");//后遍历父节点
}
}
}
(三)利用栈与队列对树进行非递归遍历(属外部遍历)
树的两种外部非递归遍历方式:深度优先(即先根)遍历、广度优先(即层次)遍历。它们需借助于栈与队列来实现。
- package tree.tree;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.Stack;
- import queue.LinkedQueue;
- public class TreeOutOrder {
- /**
- * 深度优先遍历迭代器
- *
- * @author jzj
- * @data 2009-12-17
- */
- public static class DepthOrderIterator implements Iterator {
- //栈,用来深度遍历树节点,以便回溯
- Stack stack = new Stack();
- public DepthOrderIterator(TreeNode rootNode) {
- ArrayList list = new ArrayList();
- list.add(rootNode);
- // 将根节点迭代器入栈
- stack.push(list.iterator());
- }
- //是否有下一元素
- public boolean hasNext() {
- // 如果栈为空则返回,证明没有可遍历的元素
- if (stack.empty()) {
- return false;
- } else {
- // 如果栈不为空,则取出栈顶元素(迭代器)
- Iterator iterator = (Iterator) stack.peek();
- // 这里使用简单元素(即线性排列的元素,而不是树状结构的元素)的方式来遍历
- if (!iterator.hasNext()) {
- // 如果取出迭代器已经遍历完成,则弹出迭代器,以便回退到上一(父)迭代器继续开妈以深度优先方式遍历
- stack.pop();
- // 通过递归方式继续遍历父迭代器还未遍历到的节点元素
- return hasNext();
- } else {
- // 如果找到了下一个元素,返回true
- return true;
- }
- }
- }
- // 取下一元素
- public Object next() {
- // 如果还有下一个元素,则先取到该元素所对应的迭代器引用,以便取得该节点元素
- if (hasNext()) {