zoukankan      html  css  js  c++  java
  • 深度优先算法

    深度优先算法所遵循的搜索策略是尽可能“深”地搜索一个图。在深度优先搜索中,对于最新发现的定点,如果它还有以此为起点而未探测到的边,就沿此边继续探测下去。当顶点v的所有边都已被探寻过后,搜索将回溯到发现顶点v的点。这一过程一直进行到发现从源顶点可达的所有顶点位置为止。

    用java实现的深度优先算法代码如下:

    import java.util.List;
    import java.util.ArrayList;
    
    /**
     * 栈
     */
    public class Stack<E> {
    
    	private List<E> stack = new ArrayList<E>();
    
    	/**
    	 * 进栈
    	 * 
    	 * @param 进栈元素
    	 */
    	public void push(E e) {
    		stack.add(e);
    	}
    
    	/**
    	 * 出栈
    	 * 
    	 * @return 栈顶元素
    	 */
    	public E pop() {
    		if (!isEmpty()) {
    			E result = stack.get(stack.size() - 1);
    			stack.remove(stack.size() - 1);
    			return result;
    		} else {
    			return null;
    		}
    	}
    
    	/**
    	 * 取栈顶元素
    	 * 
    	 * @return 栈顶元素
    	 */
    	public E top() {
    		if (!isEmpty()) {
    			return stack.get(stack.size() - 1);
    		} else {
    			return null;
    		}
    	}
    
    	/**
    	 * 查询栈是否为空
    	 * 
    	 * @return
    	 */
    	public boolean isEmpty() {
    		return stack.isEmpty();
    	}
    }
    
    /**
     * 边
     * 
     * @author Thief
     *
     */
    public class Edge {
    
    	public Edge(String vertexA, String vertexB) {
    		super();
    		this.vertexA = vertexA;
    		this.vertexB = vertexB;
    	}
    	
    	/**
    	 * 顶点A
    	 */
    	private String vertexA;
    
    	/**
    	 * 顶点B
    	 */
    	private String vertexB;
    
    	/**
    	 * 该边是否已经被访问
    	 */
    	boolean isVisited = false;
    
    	public String getVertexA() {
    		return vertexA;
    	}
    
    	public void setVertexA(String vertexA) {
    		this.vertexA = vertexA;
    	}
    
    	public String getVertexB() {
    		return vertexB;
    	}
    
    	public void setVertexB(String vertexB) {
    		this.vertexB = vertexB;
    	}
    
    	public boolean isVisited() {
    		return isVisited;
    	}
    
    	public void setVisited(boolean isVisited) {
    		this.isVisited = isVisited;
    	}
    
    }
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * 图
     * 
     * @author Thief
     *
     */
    public class Graph {
    
    	/**
    	 * 顶点
    	 */
    	private List<String> vertexList = new ArrayList<String>();
    
    	/**
    	 * 边
    	 */
    	private Map<String, List<Edge>> edgeMap = new HashMap<String, List<Edge>>();
    
    	/**
    	 * 向图中添加顶点
    	 * 
    	 * @param vertex
    	 *            顶点名字
    	 * @throws Exception
    	 *             当顶点已经存在时抛出异常
    	 */
    	public void addVertex(String vertex) throws Exception {
    		if (vertexList.contains(vertex)) {
    			throw new Exception("该顶点已经存在!");
    		} else {
    			vertexList.add(vertex);
    		}
    	}
    
    	/**
    	 * 向图中添加边
    	 * 
    	 * @param vertexName_A
    	 *            顶点A的名字
    	 * @param vertexName_B
    	 *            顶点B的名字
    	 * @throws Exception
    	 *             顶点不存在或边已经存在时抛出异常
    	 */
    	public void addEdge(String vertexA, String vertexB) throws Exception {
    		if (!vertexList.contains(vertexA) || !vertexList.contains(vertexB)) {
    			throw new Exception("顶点不存在!");
    		}
    
    		if (containsEdge(vertexA, vertexB)) {
    			throw new Exception("边已经存在");
    		}
    
    		if (edgeMap.containsKey(vertexA)) {
    			List<Edge> list = edgeMap.get(vertexA);
    			list.add(new Edge(vertexA, vertexB));
    		} else {
    			List<Edge> list = new ArrayList<Edge>();
    			list.add(new Edge(vertexA, vertexB));
    			edgeMap.put(vertexA, list);
    		}
    
    		if (edgeMap.containsKey(vertexB)) {
    			List<Edge> list = edgeMap.get(vertexB);
    			list.add(new Edge(vertexB, vertexA));
    		} else {
    			List<Edge> list = new ArrayList<Edge>();
    			list.add(new Edge(vertexB, vertexA));
    			edgeMap.put(vertexB, list);
    		}
    	}
    
    	/**
    	 * 判断图中该边是否已经存在
    	 * 
    	 * @param vertexA
    	 *            顶点A
    	 * @param vertexB
    	 *            顶点B
    	 * @return 如果存在返回true,否则返回false
    	 */
    	private boolean containsEdge(String vertexA, String vertexB) {
    		boolean isExist = false;
    		if (edgeMap.containsKey(vertexA)) {
    			List<Edge> list = edgeMap.get(vertexA);
    			if (list.contains(new Edge(vertexA, vertexB))) {
    				isExist = true;
    			}
    		}
    
    		return isExist;
    	}
    
    	/**
    	 * 深度优先搜索
    	 * 
    	 * @param startVertex
    	 *            起点
    	 */
    	public void DFS(String startVertex) {
    		Stack<String> stack = new Stack<String>();
    		stack.push(startVertex);
    
    		System.out.println("搜索开始。。。");
    
    		while (!stack.isEmpty()) {
    			String currentVertex = stack.top();
    
    			//判断与该顶点相连的边是否都已经被访问
    			boolean isAllVisited = true;
    			for (Edge edge : edgeMap.get(currentVertex)) {
    				if (!edge.isVisited) {
    					isAllVisited = false;
    					break;
    				}
    			}
    
    			if (isAllVisited) {
    				stack.pop();
    				if (!stack.isEmpty()) {
    					System.out.println(currentVertex + "  -->  " + stack.top());
    				}
    			} else {
    				List<Edge> listA = edgeMap.get(currentVertex);
    				for (Edge edge : listA) {
    					if (!edge.isVisited) {
    						stack.push(edge.getVertexB());
    						System.out.println(currentVertex + "  -->  "
    								+ edge.getVertexB());
    						edge.isVisited = true;
    
    						// 将边BA的访问标志置为true
    						List<Edge> listB = edgeMap.get(edge.getVertexB());
    						for (Edge item : listB) {
    							if (item.getVertexB().equals(currentVertex)) {
    								item.isVisited = true;
    							}
    						}
    						break;
    					}
    				}
    			}
    
    		}
    
    		System.out.println("搜索结束。。。");
    	}
    }
    

    测试代码如下:

    public class Test {
    
    	public static void main(String[] args) {
    		Graph graph = new Graph();
    		try {
    			graph.addVertex("A");
    			graph.addVertex("B");
    			graph.addVertex("C");
    			graph.addVertex("D");
    			graph.addVertex("E");
    			graph.addVertex("F");
    			graph.addVertex("G");
    
    			graph.addEdge("A", "B");
    			graph.addEdge("B", "C");
    			graph.addEdge("B", "D");
    			graph.addEdge("A", "E");
    			graph.addEdge("E", "F");
    			graph.addEdge("A", "G");
    
    			graph.DFS("A");
    		} catch (Exception e) {
    			System.out.println(e.getMessage());
    		}
    
    	}
    }
    

    执行结果如下:

    搜索开始。。。

    A  -->  B

    B  -->  C

    C  -->  B

    B  -->  D

    D  -->  B

    B  -->  A

    A  -->  E

    E  -->  F

    F  -->  E

    E  -->  A

    A  -->  G

    G  -->  A

    搜索结束。。。

  • 相关阅读:
    [文摘20070723]最经典的爱情观
    [转]ASP .Net C# 下 Word开发资料
    [引]如何藉由使用 Visual C# . NET 處理 Word 中的事件
    简单的搭建Web系统常用的框架页面
    Gentle 简单配置方法之一种
    在 可编辑的 Div 的 光标位置 插入 文字 或 HTML
    [转]使用FileUpload控件上传图片并自动生成缩略图、自动生成带文字和图片的水印图
    VS2005 添加 Microsoft.Office.Tools.Word.dll 等引用
    要事第一 事不过三
    VC slider用法
  • 原文地址:https://www.cnblogs.com/minisculestep/p/4970075.html
Copyright © 2011-2022 走看看