java之树的遍历

树的深度优先遍历和广度优先遍历

深度优先遍历(Depth First Search,DFS)和广度优先遍历(Breadth First Search,BFS)是两种遍历树中元素的方式。

深度优先遍历(DFS):


对于上述tree来说,DFS的遍历结果为:A B D E C F G

如果某个节点有子节点和兄弟节点,那么优先遍历子节点,左子树优先于右子树,直到子树都被深度遍历后,然后再遍历兄弟节点及其子树。

由于不会立马遍历兄弟子树,使用栈来记录未被遍历的节点,这里说一下为何要使用栈结构,栈具有先进后出的特点,所以将不需要立马遍历的结点压入栈后,也不会优先处理。

java实现

package tree;

import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class DFS {
	//深度优先遍历方法
	public static void depthFirstSearch(Node root) {
		Stack<Node> stack = new Stack<Node>();//在遍历过程中存储树的结点信息,FILO的特点记录了处理的顺序
		List<Node> list = new LinkedList<Node>();//存放遍历结果
		Node tempnode  = root;
		stack.push(tempnode);//根结点入栈
		
		while(!stack.isEmpty()) {//当栈为空,表示整棵树已经全部被遍历
			tempnode = stack.pop();
			list.add(tempnode);
			if(tempnode.rightnode != null) {
				stack.push(tempnode.rightnode);//将分支结点压入栈,为了保证先处理左子树,再处理右子树,必须先将右子树压入栈
			}
			
			if(tempnode.leftnode != null) {
				stack.push(tempnode.leftnode);
			}
			
		}
		
		for(Node tn :list) {
			System.out.print(tn.val+",");
		}
	}
	
	public static void main(String[] args) {
		Node n1 = new Node(1);
		Node n2= new Node(2);
		Node n3 = new Node(3);
		Node n4 = new Node(4);
		Node n5 = new Node(5);
		Node n6 = new Node(6);
		Node n7 = new Node(7);
		
		n1.leftnode = n2;
		n1.rightnode = n3;
		
		n2.leftnode = n4;
		n2.rightnode = n5;
		
		n3.leftnode = n6;
		n3.rightnode = n7;
		
		DFS.depthFirstSearch(n1);
	}
}
class Node{
	int val;
	Node leftnode;
	Node rightnode;
	Node(int val){
		this.val = val;
	}
}

广度优先遍历( BFS

广度优先遍历和深度优先遍历是相反的,即如果某个节点有子节点和兄弟节点,那么优先遍历兄弟节点。使用队列的数据来存储树中的结点。

package tree;

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class BFS {
	public static void breadthFirstSearch(Node root) {
		Node tempnode = root;
		Queue<Node> queue = new LinkedList<Node>();
		List<Node> list = new LinkedList<Node>();
		queue.add(tempnode);
		
		while(!queue.isEmpty()) {
			tempnode = queue.remove();
			list.add(tempnode);
			if(tempnode.leftnode!= null) {
				queue.add(tempnode.leftnode);
			}
			if(tempnode.rightnode != null) {
				queue.add(tempnode.rightnode);
			}
		}
		
		for(Node tn :list) {
			System.out.print(tn.val+",");
		}
	}
	public static void main(String[] args) {
		Node n1 = new Node(1);
		Node n2= new Node(2);
		Node n3 = new Node(3);
		Node n4 = new Node(4);
		Node n5 = new Node(5);
		Node n6 = new Node(6);
		Node n7 = new Node(7);
		
		n1.leftnode = n2;
		n1.rightnode = n3;
		
		n2.leftnode = n4;
		n2.rightnode = n5;
		
		n3.leftnode = n6;
		n3.rightnode = n7;
		
		DFS.depthFirstSearch(n1);
	}
}
class Node{
	int val;
	Node leftnode;
	Node rightnode;
	Node(int val){
		this.val = val;
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先需要定义一个结构的节点类,包含节点值和子节点列表: ```java class TreeNode { int val; List<TreeNode> children; public TreeNode(int val) { this.val = val; children = new ArrayList<>(); } } ``` 然后可以实现遍历方法,比如先序遍历: ```java public void preOrder(TreeNode root) { if (root == null) { return; } System.out.print(root.val + " "); for (TreeNode child : root.children) { preOrder(child); } } ``` 统计节点总数可以使用递归方式,每个节点的子节点数目即为它的贡献,加上1就是以它为的子的总节点数: ```java public int countNodes(TreeNode root) { if (root == null) { return 0; } int count = 1; for (TreeNode child : root.children) { count += countNodes(child); } return count; } ``` 最后可以通过一个示例来测试: ```java public static void main(String[] args) { TreeNode root = new TreeNode(1); TreeNode node2 = new TreeNode(2); TreeNode node3 = new TreeNode(3); TreeNode node4 = new TreeNode(4); TreeNode node5 = new TreeNode(5); TreeNode node6 = new TreeNode(6); TreeNode node7 = new TreeNode(7); root.children.add(node2); root.children.add(node3); root.children.add(node4); node2.children.add(node5); node2.children.add(node6); node4.children.add(node7); System.out.print("Pre-order traversal: "); preOrder(root); System.out.println(); System.out.println("Total number of nodes: " + countNodes(root)); } ``` 输出结果: ``` Pre-order traversal: 1 2 5 6 3 4 7 Total number of nodes: 7 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值