1. 深度优先搜索
深度优先遍历图的方法是,从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。
先来看一棵二叉树:
对于这棵二叉树而言,对它的一个深度优先搜索,就是一次先序遍历:遍历结果是:1 2 4 8 5 3 6 7
在对这个二叉树进行DFS搜索时,我们先来创建一棵这样的二叉树
package test;
public class DFSBinaryTree {
public static void main(String[] args) {
//创建节点
Node root=new Node(1);
Node node2=new Node(2);
Node node3=new Node(3);
Node node4=new Node(4);
Node node5=new Node(5);
Node node6=new Node(6);
Node node7=new Node(7);
Node node8=new Node(8);
//连接节点
root.left=node2;
root.right=node3;
node2.left=node4;
node2.right=node5;
node3.left=node6;
node3.right=node7;
node4.left=node8;
}
}
class Node{
Node left;
Node right;
int val;
public Node(int val)
{
this.val=val;
}
}
- DFS的递归形式
void DFS(Node root)
{
if(root==null)
return;
System.out.print(root.val+" ");
DFS(root.left);
DFS(root.right);
}
在主函数中调用:
DFSBinaryTree t=new DFSBinaryTree();
t.DFS(root);
完整代码:
package test;
public class DFSBinaryTree {
public static void main(String[] args) {
//创建节点
Node root=new Node(1);
Node node2=new Node(2);
Node node3=new Node(3);
Node node4=new Node(4);
Node node5=new Node(5);
Node node6=new Node(6);
Node node7=new Node(7);
Node node8=new Node(8);
//连接节点
root.left=node2;
root.right=node3;
node2.left=node4;
node2.right=node5;
node3.left=node6;
node3.right=node7;
node4.left=node8;
DFSBinaryTree t=new DFSBinaryTree();
t.DFS(root);
}
void DFS(Node root)
{
if(root==null)
return;
System.out.print(root.val+" ");
DFS(root.left);
DFS(root.right);
}
}
class Node{
Node left;
Node right;
int val;
public Node(int val)
{
this.val=val;
}
}
可以看到输出结果和我们之前写的前序遍历结果是一样的
- DFS的非递归形式
DFS的非递归形式要采用栈,第一次先把根节点压进栈,然后再压右子节点,是右子节点,然后再压左子节点,然后不断的压栈,出栈访问
void DFSNotRecursive(Node root)
{
Stack<Node> st=new Stack<>();
st.push(root);
while(!st.isEmpty())
{
Node top=st.pop();//获取栈顶节点
System.out.print(top.val+" ");
if(top.right!=null)//先压右子节点
st.push(top.right);
if(top.left!=null)
st.push(top.left);
}
}
结果和递归形式的DFS一致
2.广度优先搜索
广度优先搜索一般采用队列形式的非递归形式,对于一棵二叉树而言,广度优先搜索可以实现层序遍历,以本文的二叉树为例,层序遍历的结果应该是:1 2 3 4 5 6 7 8
void BFS(Node root)
{
Queue<Node> q=new LinkedList<>();
q.offer(root);//将节点添加到队尾
while(!q.isEmpty())
{
Node cur=q.poll();//获取队首节点并将其移除队列
System.out.print(cur.val+" ");
if(cur.left!=null)
q.offer(cur.left);
if(cur.right!=null)
q.offer(cur.right);
}
}
全文代码:
package test;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class DFSBinaryTree {
public static void main(String[] args) {
//创建节点
Node root=new Node(1);
Node node2=new Node(2);
Node node3=new Node(3);
Node node4=new Node(4);
Node node5=new Node(5);
Node node6=new Node(6);
Node node7=new Node(7);
Node node8=new Node(8);
//连接节点
root.left=node2;
root.right=node3;
node2.left=node4;
node2.right=node5;
node3.left=node6;
node3.right=node7;
node4.left=node8;
DFSBinaryTree t=new DFSBinaryTree();
t.DFS(root);
System.out.println();
t.DFSNotRecursive(root);
System.out.println();
t.BFS(root);
}
void DFS(Node root)
{
if(root==null)
return;
System.out.print(root.val+" ");
DFS(root.left);
DFS(root.right);
}
void DFSNotRecursive(Node root)
{
Stack<Node> st=new Stack<>();
st.push(root);
while(!st.isEmpty())
{
Node top=st.pop();//获取栈顶节点
System.out.print(top.val+" ");
if(top.right!=null)//先压右子节点
st.push(top.right);
if(top.left!=null)
st.push(top.left);
}
}
void BFS(Node root)
{
Queue<Node> q=new LinkedList<>();
q.offer(root);//将节点添加到队尾
while(!q.isEmpty())
{
Node cur=q.poll();//获取队首节点并将其移除队列
System.out.print(cur.val+" ");
if(cur.left!=null)
q.offer(cur.left);
if(cur.right!=null)
q.offer(cur.right);
}
}
}
class Node{
Node left;
Node right;
int val;
public Node(int val)
{
this.val=val;
}
}