图--1.广度优先搜索和深度优先搜
2017-03-16 20:16
615 查看
1.图的表示
(1)图G的顶点数有n个,边数e,则无向图满足0<=e<=n(n-1)/2 ; 有向图满足 0<=e<=n(n-1) ;如果边满的话就叫完全图
(2)子图、连通图、强连通图这里不再强调了
(3)图的表示:邻接矩阵和邻接表,这里不再重复了。对于无向图 邻接矩阵第i行中非0的个数和=节点vi的度,有向图就是出度,邻接矩阵占用空间O(n^2)
(4)一个图的邻接矩阵是唯一的,但是邻接表不是,因为邻接表表示中,各边表节点的链接次序取决于建立邻接表的算法以及边的输入次序。邻接表的空间复杂度O(n+e)
2.广度优先搜索(BFS)
广度优先搜索类似于树的层次遍历,尽可能的横向进行搜索:首先访问节点vi 得到它的所有邻接点w1...wt,然后再依次访问w1...wt,所以采用队列来保存被访问过的节点
A -> C -> D -> F -> B -> G -> E
A -> B -> C -> E -> F -> D -> G(以上两幅图来自网友,表示感谢)
每个顶点最多入队出队一次,遍历图的过程实际就是寻找队列中顶点的邻接点的过程,当图以邻接表存储时时间复杂度为O(v+e),空间复杂度为O(n)队列 。经BFS搜索得到BFS序列,该序列不是唯一的,与出发点和图的存储结构有关。
3.深度优先搜索(DFS)
深度优先搜索尽可能纵深方向进行搜索:先访问节点vi, 然后从 vi 出发开始搜索它的一个邻接点 vj,如果vj没访问过 搜索vj的邻接点。
A->C->B->D->F->G->E
a b c e d f g
当以双链式结构作为图的结构存储时,深度优先的复杂度是O(v+e),
图的深度优先也可以使用栈以非递归的形式实现:初始节点入栈,当栈不空时,重复处理栈顶元素,若未访问,访问并设置访问标识,将其未访问的邻接点入栈
/**
*
*/
package graph_search;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
/**
* 邻接表表示的无向图
* @author LingLee
*
*/
class GraphNode{//节点类
public List<GraphEdge> edgeList=null;
private String label="";
public GraphNode(String label){
this.label=label;
if(edgeList==null){
edgeList=new ArrayList();
}
}
//给当前节点添加一条边
public void addEdgeList(GraphEdge edge){
edgeList.add(edge);
}
public String getLabel(){
return label;
}
}
class GraphEdge{//边类
private GraphNode left;//左边的点
4000
private GraphNode right;
public GraphEdge(GraphNode left,GraphNode right){
this.left=left;
this.right=right;
}
public GraphNode getLeft(){
return left;
}
public GraphNode getRight(){
return right;
}
}
public class ListUDG {//图结构
private List<GraphNode> nodes=null;//图中点集合
public void initGraph(int n){
if(nodes==null){
nodes=new ArrayList();
}
GraphNode node=null;
for(int i=0;i<n;i++){
node=new GraphNode(String.valueOf(i));
nodes.add(node);
}
}
public void initGraph(int n,boolean b){
initGraph(n);
GraphEdge edge01 = new GraphEdge(nodes.get(0), nodes.get(1));
GraphEdge edge02 = new GraphEdge(nodes.get(0), nodes.get(2));
GraphEdge edge13 = new GraphEdge(nodes.get(1), nodes.get(3));
GraphEdge edge14 = new GraphEdge(nodes.get(1), nodes.get(4));
GraphEdge edge25 = new GraphEdge(nodes.get(2), nodes.get(5));
GraphEdge edge26 = new GraphEdge(nodes.get(2), nodes.get(6));
GraphEdge edge37 = new GraphEdge(nodes.get(3), nodes.get(7));
GraphEdge edge47 = new GraphEdge(nodes.get(4), nodes.get(7));
GraphEdge edge56 = new GraphEdge(nodes.get(5), nodes.get(6));
nodes.get(0).addEdgeList(edge01);
nodes.get(0).addEdgeList(edge02);
nodes.get(1).addEdgeList(edge13);
nodes.get(1).addEdgeList(edge14);
nodes.get(2).addEdgeList(edge25);
nodes.get(2).addEdgeList(edge26);
nodes.get(3).addEdgeList(edge37);
nodes.get(4).addEdgeList(edge47);
nodes.get(5).addEdgeList(edge56);
}
public void initGraph(){
initGraph(8,false);
}
//广度优先
public void BFS(GraphNode node){
List<GraphNode> visited=new ArrayList();//已访问过的节点
Queue<GraphNode> q=new LinkedList();//d队列存储依次要遍历的元素
q.offer(node);//根节点加入队列
while(!q.isEmpty()){
GraphNode curNode=q.poll();//队首元素 也是目前该访问的节点
if(!visited.contains(curNode)){//没有访问过
visited.add(curNode);
System.out.print(curNode.getLabel()+"->");
for(int i=0;i<curNode.edgeList.size();i++){//访问节点curnode的所有邻接点
q.offer(curNode.edgeList.get(i).getRight());//将邻接点加入队列中
}
}
}
}
//深度优先
public void DFS(GraphNode node,List<GraphNode> visited){//递归法
if(visited.contains(node)){
return;
}
visited.add(node);//
System.out.print(node.getLabel()+"->");
for(int i=0;i<node.edgeList.size();i++){
DFS(node.edgeList.get(i).getRight(),visited);//对节点node的邻接点递归深度搜索
}
}
//深度优先非递归方法 借助栈
public void DFS2(GraphNode node){
List<GraphNode> visited=new ArrayList();
LinkedList s=new LinkedList();
s.push(node);
while(!s.isEmpty()){
GraphNode curNode=(GraphNode)s.pop();
if(!visited.contains(curNode)){
visited.add(curNode);
System.out.print(curNode.getLabel()+"->");
for(int i=0;i<curNode.edgeList.size();i++){
GraphNode next=curNode.edgeList.get(i).getRight();
//System.out.println("节点:"+i);
if(!visited.contains(next)){//如果邻接点没访问过 则压入栈
s.push(next);
//System.out.println("节点:"+i+"入栈");
}
}
}
}
}
public static void main(String[] args){
ListUDG udg=new ListUDG();
udg.initGraph();
GraphNode node=new GraphNode(String.valueOf(0));
System.out.println("广度优先搜索:");
udg.BFS(udg.nodes.get(0));
System.out.println();
System.out.println("递归深度优先搜索:");
List<GraphNode> visited=new ArrayList();
udg.DFS(udg.nodes.get(0), visited);
System.out.println();
System.out.println("非递归深度优先搜索:");
udg.DFS2(udg.nodes.get(0));
}
}
(1)图G的顶点数有n个,边数e,则无向图满足0<=e<=n(n-1)/2 ; 有向图满足 0<=e<=n(n-1) ;如果边满的话就叫完全图
(2)子图、连通图、强连通图这里不再强调了
(3)图的表示:邻接矩阵和邻接表,这里不再重复了。对于无向图 邻接矩阵第i行中非0的个数和=节点vi的度,有向图就是出度,邻接矩阵占用空间O(n^2)
(4)一个图的邻接矩阵是唯一的,但是邻接表不是,因为邻接表表示中,各边表节点的链接次序取决于建立邻接表的算法以及边的输入次序。邻接表的空间复杂度O(n+e)
2.广度优先搜索(BFS)
广度优先搜索类似于树的层次遍历,尽可能的横向进行搜索:首先访问节点vi 得到它的所有邻接点w1...wt,然后再依次访问w1...wt,所以采用队列来保存被访问过的节点
A -> C -> D -> F -> B -> G -> E
A -> B -> C -> E -> F -> D -> G(以上两幅图来自网友,表示感谢)
每个顶点最多入队出队一次,遍历图的过程实际就是寻找队列中顶点的邻接点的过程,当图以邻接表存储时时间复杂度为O(v+e),空间复杂度为O(n)队列 。经BFS搜索得到BFS序列,该序列不是唯一的,与出发点和图的存储结构有关。
3.深度优先搜索(DFS)
深度优先搜索尽可能纵深方向进行搜索:先访问节点vi, 然后从 vi 出发开始搜索它的一个邻接点 vj,如果vj没访问过 搜索vj的邻接点。
A->C->B->D->F->G->E
a b c e d f g
当以双链式结构作为图的结构存储时,深度优先的复杂度是O(v+e),
图的深度优先也可以使用栈以非递归的形式实现:初始节点入栈,当栈不空时,重复处理栈顶元素,若未访问,访问并设置访问标识,将其未访问的邻接点入栈
/**
*
*/
package graph_search;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
/**
* 邻接表表示的无向图
* @author LingLee
*
*/
class GraphNode{//节点类
public List<GraphEdge> edgeList=null;
private String label="";
public GraphNode(String label){
this.label=label;
if(edgeList==null){
edgeList=new ArrayList();
}
}
//给当前节点添加一条边
public void addEdgeList(GraphEdge edge){
edgeList.add(edge);
}
public String getLabel(){
return label;
}
}
class GraphEdge{//边类
private GraphNode left;//左边的点
4000
private GraphNode right;
public GraphEdge(GraphNode left,GraphNode right){
this.left=left;
this.right=right;
}
public GraphNode getLeft(){
return left;
}
public GraphNode getRight(){
return right;
}
}
public class ListUDG {//图结构
private List<GraphNode> nodes=null;//图中点集合
public void initGraph(int n){
if(nodes==null){
nodes=new ArrayList();
}
GraphNode node=null;
for(int i=0;i<n;i++){
node=new GraphNode(String.valueOf(i));
nodes.add(node);
}
}
public void initGraph(int n,boolean b){
initGraph(n);
GraphEdge edge01 = new GraphEdge(nodes.get(0), nodes.get(1));
GraphEdge edge02 = new GraphEdge(nodes.get(0), nodes.get(2));
GraphEdge edge13 = new GraphEdge(nodes.get(1), nodes.get(3));
GraphEdge edge14 = new GraphEdge(nodes.get(1), nodes.get(4));
GraphEdge edge25 = new GraphEdge(nodes.get(2), nodes.get(5));
GraphEdge edge26 = new GraphEdge(nodes.get(2), nodes.get(6));
GraphEdge edge37 = new GraphEdge(nodes.get(3), nodes.get(7));
GraphEdge edge47 = new GraphEdge(nodes.get(4), nodes.get(7));
GraphEdge edge56 = new GraphEdge(nodes.get(5), nodes.get(6));
nodes.get(0).addEdgeList(edge01);
nodes.get(0).addEdgeList(edge02);
nodes.get(1).addEdgeList(edge13);
nodes.get(1).addEdgeList(edge14);
nodes.get(2).addEdgeList(edge25);
nodes.get(2).addEdgeList(edge26);
nodes.get(3).addEdgeList(edge37);
nodes.get(4).addEdgeList(edge47);
nodes.get(5).addEdgeList(edge56);
}
public void initGraph(){
initGraph(8,false);
}
//广度优先
public void BFS(GraphNode node){
List<GraphNode> visited=new ArrayList();//已访问过的节点
Queue<GraphNode> q=new LinkedList();//d队列存储依次要遍历的元素
q.offer(node);//根节点加入队列
while(!q.isEmpty()){
GraphNode curNode=q.poll();//队首元素 也是目前该访问的节点
if(!visited.contains(curNode)){//没有访问过
visited.add(curNode);
System.out.print(curNode.getLabel()+"->");
for(int i=0;i<curNode.edgeList.size();i++){//访问节点curnode的所有邻接点
q.offer(curNode.edgeList.get(i).getRight());//将邻接点加入队列中
}
}
}
}
//深度优先
public void DFS(GraphNode node,List<GraphNode> visited){//递归法
if(visited.contains(node)){
return;
}
visited.add(node);//
System.out.print(node.getLabel()+"->");
for(int i=0;i<node.edgeList.size();i++){
DFS(node.edgeList.get(i).getRight(),visited);//对节点node的邻接点递归深度搜索
}
}
//深度优先非递归方法 借助栈
public void DFS2(GraphNode node){
List<GraphNode> visited=new ArrayList();
LinkedList s=new LinkedList();
s.push(node);
while(!s.isEmpty()){
GraphNode curNode=(GraphNode)s.pop();
if(!visited.contains(curNode)){
visited.add(curNode);
System.out.print(curNode.getLabel()+"->");
for(int i=0;i<curNode.edgeList.size();i++){
GraphNode next=curNode.edgeList.get(i).getRight();
//System.out.println("节点:"+i);
if(!visited.contains(next)){//如果邻接点没访问过 则压入栈
s.push(next);
//System.out.println("节点:"+i+"入栈");
}
}
}
}
}
public static void main(String[] args){
ListUDG udg=new ListUDG();
udg.initGraph();
GraphNode node=new GraphNode(String.valueOf(0));
System.out.println("广度优先搜索:");
udg.BFS(udg.nodes.get(0));
System.out.println();
System.out.println("递归深度优先搜索:");
List<GraphNode> visited=new ArrayList();
udg.DFS(udg.nodes.get(0), visited);
System.out.println();
System.out.println("非递归深度优先搜索:");
udg.DFS2(udg.nodes.get(0));
}
}
相关文章推荐
- 深度优先搜索和广度优先搜索的代码实现
- File&&文件搜索深度优先和广度优先
- C语言搜索算法之深度优先搜索和广度优先搜索
- 深度优先搜索与广度优先搜索
- 广度优先搜索与深度优先搜索的 java 实现
- 广度优先搜索二叉树,并返回节点深度
- 数据结构和算法总结(一):广度优先搜索BFS和深度优先搜索DFS
- 图的遍历—深度、广度优先搜索
- 图基本算法 图搜索基于邻接表的(广度优先、深度优先)
- 深度优先搜索DFS和广度优先搜索BFS的总结
- 深度优先搜索和广度优先搜索
- 深度优先搜索和广度优先搜索
- 深度优先搜索和广度优先搜索的比较与分析
- 深度优先搜索和广度优先搜索的深入讨论(转自百度文库)
- 广度 / 深度优先搜索
- 邻接矩阵的广度优先搜索和深度优先搜索
- 深度优先搜索和广度优先搜索的比较与分析
- 22.基于 邻接表 表示的 深度优先搜索dfs 和 广度优先搜索bfs
- 数据结构4-深度优先搜索和广度优先搜索
- 算法——基本的图算法:广度优先搜索、深度优先搜索