`
endual
  • 浏览: 3557531 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java 图的最小生成树问题 (代码自己写)

 
阅读更多

最小生成树是基于无无向图,并且是没有权值的图的。它的实现可以用深度遍历还有广度遍历实现

本代码是基于图的,所以和前面的    java 图 的那个代码是一样的 

不同是加入了  生成最小生成图的代码

 

 

老习惯理论:

/**
 * 
详细代码后面会给出来的,现在只是大概的只是代码怎么写,怎么个思路
package endual;

public class ShortTree {

	//mst
	public void mst() {
		
	
		while (!(theStack).isEmpty()) {
			
			int currentVertex = theStack.peek() ;
			//get next univisited heighbor
			//找到下一个邻居的未访问的顶点
			
			int v = getAdUnvisitedVertex(currentVertex) ;
			if (v == -1) {//如果不存在,那么跳出一个栈里面的作为当前的点
				theStack.pop() ; 
			}
			else { //否则就是要
				
				vertexList[v].isVisited = true ; //已经被访问过了的。然后就是true了
				theStack.push(v) ; //压入栈 
				
				displayVertex(currentVertex) ; //打印出访问过的点
				displayVertex(v) ;
				System.out.println(" * * ");
				
				
			}
			
		}
		
	}
	
	
	for(int i=0; i < nVertex; i++) {
		
		vertext[j].isVisited() = false ;
	}
	
}
 */

 

 

 

 

最小生成树其实找的是连接顶点的用最少的边,并不用去考虑边的长度,这个不是带权的边,所以是不用考虑的。

需要注意的是

    最小生成树的边数E总是比该图的所以顶点之和少一个

  E = V -1 ;

 

 记住,不必关心边的长度,并不需要找到一条最短路径,而是要找最少数量的边。

 

 创建最小生成树的算法与搜索的算法几乎是相同的。它同样可以基于广度搜索或者是深度搜索算法来实现

 

 我们用深度搜索算法来实现。

 

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
import java.util.concurrent.ArrayBlockingQueue;

import javax.management.Query;

/**
 * 下面来看下Graph类,包含的是创建连接链表和连接矩阵的方法,以向Graph对象插入顶点和边的方法
 * (最小生产树的方法的代码在最后面,代码请看 前面的图那个文章  ,这只是一部分代码)
 * @author Endual
 *
 */
public class Graph {

	private  final int MAX_VERTS = 20 ;
	private  Vertex[] vertexList ; //存放顶点的数组
	private  int adjMat[][] ; //表示用矩阵的形式来表示边有没有
	private  int nVerts ; //当前的图中有多少个顶点了
	
	public Graph() {
		super();
		this.vertexList = new Vertex[this.MAX_VERTS];
		this.nVerts = 0 ;
    this.initialAdjMat () ; //初始化矩阵的
	}
	//初始化矩阵的
	private void initialAdjMat() {
		
		for (int i=0; i < this.MAX_VERTS; i++) {
			for (int j=0; j < this.MAX_VERTS; j++) {
				this.adjMat[i][j] = 0 ; //初始数组
			}
		}
		
	}
	//////////////////////////////////////////////////////////////////////////////////////////////
	//创建图 = 创建顶点和创建边,两个步骤是分开的
	//添加顶点
	public void addVertex(char lab) {
		
		Vertex ver = new Vertex(lab) ;
		this.vertexList[this.nVerts] = ver ;
		this.nVerts++ ;
		
	}
	
	//创建边(start 和 end 要有范围的 从0 到 N-1)
	public void addEdge(int start, int end) {
		
		this.adjMat[start][end] = 1 ;
		this.adjMat[end][start] = 1 ;
		
	}
   ///////////////////////////////////////////////////////////////////////////////////////////////////
	//显示一个顶点
	public void displayVertex(int v) {
		
		System.out.println(this.vertexList[v].getLabel()) ;
		
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * 搜索
	 * 在图中实现的最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点可以到达哪些顶点。例如,可以想象要找出美国有多少个城市
	 * 可以从kansan乘坐旅行车到达(当然了中间是不能换车的)。一些城市可以直达,而有些城市因为没有旅行列车服务而不能到达。
	 * 有些地方即使有列子服务也不能到达,因为他们的铁轨不能和出发或者沿途的标准铁轨系统相连。
	 * 
	 * 还有一种情况就是需要找出所有的当前顶点可以到达的顶点。
	 * 假设有这么一张图,现在需要一种算法来提供系统的方法,从某个特定顶点开始,沿着边移动到其他顶点,移动完毕后,需要保证访问了喝
	 * 起始点相连的每一个顶点。
	 * 有两种常用的方法可以用来搜索图;深度优先搜索和广度优先搜索,他们最终都会到达所有连通的顶点
	 *
	 * 深度优先搜索通过栈来实现,而广度优先搜索通过队列实现。
	 * 
	 * 
	 * 深度优先搜索
	 * 
	 * 在搜索到尽头的时候,深度优先搜索用栈记住下一步的走向,这里展示了一个例子,
	 * 为了实现深度优先搜索,找到一个起始本例的顶点是A
	 * 需要做的三件事情:
	 * 首先是访问该顶点,然后是把该节点放入到栈中去,以便记住它
	 * 最后标记该节点,这样就不会再访问它了
	 * 下面就可以访问任何与顶点A相连的顶点了,只要还没有访问过它,假设顶点按字母顺序访问,所以下面访问顶点B。然后标记它,放入栈中。
	 *  已经访问过B,做相同的事情,找下一个为访问的节点的顶点,也就是F,这个过程就叫做规则1。
	 *  
	 *  规则1:
	 *       如果可能,访问一个邻接的未访问顶点,标记它,并把它放入到栈中。
	 *   
	 *   再次应用规则1,这次访问顶点H。然而,这里还需要做一些事情,因为没有和H邻接的未访问顶点。
	 *   
	 *   规则2.
	 *      当不能执行规则1的时候,如果栈不空,就从栈中探出一个顶点
	 *      
	 *       根据这条规则,从栈中探出H,这样就又回到了顶点F,F也没有和邻接且邻接没有访问的顶点了。那么再弹出F,这回到顶点B。这时
	 *  只有顶点A在栈中了。
	 *       然而A还没有访问过的连接点,所以访问下一个顶点C,但是C又是在这一条线路的终点,所以栈中弹出它,再次回到A点。接着访问D,G和I。
	 *  当到达I时,把它们都弹出栈,现在回到A然后访问E,最后再次回到A
	 *     
	 *   规则3
	 *      如果不能执行规则1 和规则 2,那么就完成了整一个深度搜索的过程了
	 *  栈的内容就是刚才起始顶点到各个顶点访问的整个过程。从起始顶点出发访问下一个顶点时,就是把这个顶点入栈,回到起始顶点,出栈
	 *  访问顶点的顺序是ABFHCDGIE
	 *  
	 *    深度优先搜索算法要得到距离起始点最远的顶点,然后再不能继续前进的时候返回,使用深度这个属于表示与起始点的距离,便可以理解深度优先
	 *    搜索的意义。
	 *    
	 *    模拟问题
	 *    
	 *    深度优先搜索与迷宫问题有类似的,迷宫在英国很流行,可以由一方给另一方设置障碍,由另一方想办法通过,迷宫由狭小的过道和过道的交汇点组成
	 *    
	 *                                                                                                                                             
	 *      JAVA代码 深度优先搜索的关键在于能够找到与某一顶点邻接且没有访问过的顶点。邻接矩阵是关键,找到指定顶点所在的行。第一列开始向后寻找值为1的列;
	 *      列号是邻接顶点的号码。检验这个顶点是不是被访问过的,如果是这样的,那么就是要访问的下个顶点,如果该行没有顶点既等于1,且又是没有访问过的,那么
	 *      与指定点相邻接的顶点就全部访问过了。这个过程在下面的代码中实现                                                                                                                                   
	 *                                                                                                                                             
	 * 
	 * 
	 */
	
	
	
	public int getAdjUnivisitedVertex(int v) { //从哪个顶点开始访问
		
		for(int j=0; j < this.nVerts; j++) {
			if (this.adjMat[v][j] == 1 && this.vertexList[j].isVisisted == false) {
				return j ;
			}
			
		}
		
		return -1 ;//如果没有访问到,那么返回-1 ;
	}
	
	//考察dfs()方法,这个方法实际执行了深度的优先搜索。包含三条规则。它循环执行,知道栈为空,每次循环中,有四件事情
	/**
	 * 1. 用peek()方法检查栈顶的顶点
	 * 2. 试图找到这个顶点还未访问的邻接点
	 * 3. 如果找没有找到,出栈
	 * 4. 如果找到了这样的顶点,访问这个顶点,并且把它压入栈
	 */
	//深度搜索
	
	public void dfs() {
		
		Stack theStack = new Stack() ;
		//所谓遍历是从第一个顶点开始的 也是 vertesList[0]开始的
		this.vertexList[0].isVisisted = true ;
		this.displayVertex(0) ;
		theStack.push(0) ;
		
		while(!theStack.isEmpty()) {
			int v = this.getAdjUnivisitedVertex((Integer) theStack.peek()) ;
			if (-1 == v) { //已经被访问过的
				theStack.pop() ;//弹出一个
				
			}
			else {
				this.vertexList[v].isVisisted = true ;
				this.displayVertex(v) ;
				theStack.push(v) ;
			}
			
		}
	
		//stack 是空的话,就做
		for(int i=0; i < this.nVerts; i++) {
			
			this.vertexList[i].isVisisted = false ; //重新初始化节点,为下次的使用
		}
		
	} //end dfs
	
	/**
	 * 广度优先搜索
	 * 
	 *   正如深度优先搜索中看到的,算法表现得好像要尽快地远离起始点的。相反,在广度优先搜索中,算法好像要尽可能地靠近起始点
	 *   它首先访问的是顶点的所有邻接点,然后再访问较远的区域。这种搜索不能用栈,只能用到队列来实现
	 *   
	 *   一个例子
	 *   
	 *   A是起始点,所有访问它,并且标记为当前空的顶点。然后应用下面几条规则
	 *   
	 *   规则1
	 *      访问下一个未来访问的邻接点(如果存在), 这个顶点必须是当前顶点的邻接点,标记它,并把它插入到队列中
	 *      (当前节点为改变)
	 *   规则2
	 *      如果因为已经没有未访问顶点而不能执行规则1, 那么从队列头取一个顶点(如果有),并且使得成为当前的顶点。
	 *      (当前节点改变了)
	 *   规则3
	 *      如果因为队列为空而不能执行规则2.那么广度优先搜索的到此就结束了
	 *      
	 *      
	 *      A-------B--------C------D
	 *       \       |      X
	 *        \      |      |
	 *         \-----e------F----G
	 *                     |  
	                       Y----H
	 
	   
	      在每一个时刻队列中包含的顶点是那些本身已经被访问,而它的邻居还未被访问的顶点。(对比深度优先搜索,栈的内容是起始点
	      到当前顶点经过的所有顶点)顶点访问的顺序。
	      
	     深度优先遍历和广度优先遍历的异同点 
	       可以认为广度优先搜索就像往水中投入石块,水波纹扩展的过程===对于喜爱流行病学的人来说,就好比流感通过航空旅行客从一个城市
	       到另一个城市了。首先是相距起始点只有一条边的所有顶点被访问,然后是相距两条边的所有顶点被访问,一次类推
	       
	 */
	
	
	
	//广度搜索与深度类似的,只是用队列代替了栈,嵌套的循环代替了单层循环。外层循环等待队列为空,而内层循环依次寻找当前顶点的未访问邻接点
    //下面是代码
	
	public  void bfs() {
		
		Queue theQueue = new LinkedList();  
		
		this.vertexList[0].isVisisted = true ;
		this.displayVertex(0) ;
		theQueue.add(0) ;
		
		int v2 ;
		
		while (!theQueue.isEmpty()) {
			
			int v1 = (Integer) theQueue.remove() ;
			v2 = this.getAdjUnivisitedVertex(v1) ;
			while (v2 != -1) {
				
				this.vertexList[v2].isVisisted = true ;
				this.displayVertex(v2) ;
				theQueue.add(v2) ;
			}
			
		}
		
		for(int i=0; i < this.nVerts; i++) {
			
			this.vertexList[i].isVisisted = false ; //重新初始化节点,为下次的使用
		}
	}
	
	/*
	 * 
	 * 
	 * 请看我请看我请看我
	 * 
	 * 
	 * 
	 * 
	 */
	
	
	//最小生成树的代码
	public void mst() {
		Stack theStack = new Stack() ;
		this.vertexList[0].isVisisted = true ; //从顶点开是访问,所以立马设置ture
		//得到它的邻接的
	    
		theStack.push(0) ; //从节点0开始访问,压入到栈中
		
		while (!theStack.isEmpty()) { //当前的栈不为空
			
		  int currentVertex = (Integer) theStack.peek() ; //只是看,没删删除掉最上面的那个元素
		  //取得当前顶点的邻接顶点
		  int v = this.getAdjUnivisitedVertex(currentVertex) ;			
			if(v == -1) {
				
				theStack.pop() ;
			} //如果没有找到当前顶点的邻接的顶点,那么弹出一个顶点
			else {
				
				//否则就是访问
				this.vertexList[v].isVisisted = true ;
				theStack.push(v) ;
				
				this.displayVertex(currentVertex) ; //打印当前的节点
			    this.displayVertex(v) ; //大于邻接节点
			    System.out.println(" ") ;
				
			} //end 当这个栈的空间都没有的时候,那么就停止操作
		}
		
		//初始化图的顶点未访问过的,下次用的时候还是还可以访问
		
		for(int i=0; i < this.nVerts; i++) {
			this.vertexList[i].isVisisted = false ; //全部设置成没有访问过的
		}
			
		
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

}
 

 

分享到:
评论

相关推荐

    图的最小生成树java代码

    在这个“图的最小生成树Java代码”项目中,我们可以看到三个关键文件:`Graph.java`, `TestGraph.java`, 和 `Vertex.java`。每个文件都有其特定的作用: 1. **Graph.java**: 这个文件通常会定义一个图类,用于存储...

    java最小生成树

    如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题。(1)利用克鲁斯卡尔算法求网的最小生成树。 (2)实现教科书中定义的抽象数据类型MFSet。以此表示构造生成树过程中的连通分量。 (3)以文本形式输出...

    代码 最小生成树Prim算法代码

    代码 最小生成树Prim算法代码代码 最小生成树Prim算法代码代码 最小生成树Prim算法代码代码 最小生成树Prim算法代码代码 最小生成树Prim算法代码代码 最小生成树Prim算法代码代码 最小生成树Prim算法代码代码 最小...

    java代码数据结构最小生成树代码

    最小生成树是图论中的一个重要概念,用于寻找加权无向图中连接所有顶点的边的集合,使得这些边的总权重尽可能小。在这个Java编程项目中,开发者使用了MyEclipse集成开发环境来实现这个算法,允许用户交互式地创建...

    用Java利用prim算法实现最小生成树

    最小生成树(Minimum Spanning Tree, MST)是指在一个加权的无向图中找到一棵包含所有顶点的生成树,使得所有边的权重之和最小。最小生成树在实际应用中有着广泛的应用场景,比如网络设计、电路板布线、交通网络规划...

    kruskal算法求最小生成树 java

    ### Kruskal算法求最小生成树的Java实现 #### 一、Kruskal算法简介 Kruskal算法是一种用于寻找图中的最小生成树(Minimum Spanning Tree, MST)的算法。最小生成树是指在一个加权无向图中,连接所有顶点形成的树,...

    用Java编写的最小生成树代码

    在提供的压缩包文件"最小生成树"中,很可能包含了Java实现的Prim或Kruskal算法的源代码。通过阅读和理解这些代码,你可以深入学习如何在实际编程中应用这些算法。同时,也可以尝试自己实现这些算法,通过比较不同...

    Java贪心算法 最小生成树 单源最短路径 单机调度问题

    在Java编程中,贪心算法被广泛应用于解决复杂问题,如最小生成树、单源最短路径和单机调度问题。以下是这三个核心知识点的详细解释: 1. **最小生成树(Minimum Spanning Tree, MST)**: - 最小生成树问题是在一个...

    java算法分析与设计之最小生成树(prim算法)源代码

    java算法分析与设计之最小生成树(prim算法)源代码 算法作为计算机专业学生的必修课,同时也是软件开发过程中必备的编程思想,对学习研究计算机专业意义重大;正因为这门课程难,所以除了相关方面的书籍,网络资源少...

    Prim算法与Kruskal算法求最小生成树

    最小生成树是图论中的一个重要概念,用于寻找一个无向加权图的边集合,使得这些边连接了图中的所有顶点,同时整个边集合的总权重尽可能小。在这个问题中,Prim算法和Kruskal算法是两种常用的方法。 1. Prim算法: ...

    数据结构课程设计 最小生成树问题报告

    最小生成树问题旨在寻找一个无向加权图的边子集,使得这个子集构成的树连接了图中的所有顶点,并且其总权重最小。这一问题在实际应用中广泛出现,例如电信网络的设计、道路建设规划等场景。 在解决最小生成树问题时...

    Kruskal实现最小生成树代码

    最后,`最小生成树-Kruskal`这个文件可能是Kruskal算法的具体实现代码,可能包含一个或多个文件,如C++、Java、Python等语言的实现。通过阅读和理解这些代码,你可以更深入地掌握Kruskal算法的细节以及并查集的运用...

    java从文件中读取数据Kruskal算法解决最小生成树

    在这个问题中,我们关注的是如何利用Java编程语言,结合Kruskal算法来解决最小生成树的问题,并且从文件中读取数据来实现这一过程。 Kruskal算法是一种贪心算法,其基本思想是按照边的权重从小到大依次考虑,每次...

    最小生成树的实现原理及java代码实现

    ### 最小生成树的实现原理及Java代码实现 #### 最小生成树概念解析 最小生成树(Minimum Spanning Tree, MST)是指在一个无向、连通的加权图中找到一棵包含所有顶点的树,使得这棵树上的所有边的权值之和最小。它在...

    最小生成树Kruskal算法(经典)

    经典算法解决最小生成树问题,清晰易懂的源代码,Java语言实现的。

    Java语言实现使用Prim(普利姆)算法求最小生成树(源代码)

    本文通过详细的理论解释和Java代码实现,展示了如何使用Prim算法来求解最小生成树问题。Prim算法不仅在理论上具有重要意义,在实际应用中也十分广泛,如在网络设计、电路板布局等领域都有着不可替代的作用。通过深入...

    使用Java实现的基于最小生成树的旅行商问题.zip

    在这个项目中,使用Java编程语言实现了基于最小生成树的旅行商问题解决方案。最小生成树(Minimum Spanning Tree, MST)是图论中的一个重要概念,用于找到连接所有顶点的无环加权边的集合,使得这些边的总权重最小。...

    课程设计:最小生成树

    输入conf.txt地址 单击执行后会画出该树的图,其中红色的为最小生成树 文件格式 0 12 26 12 0 45 26 45 0 Java初学者代码 仅供参考

    Java 使用克鲁斯卡尔求最小生成树(源代码)

    ### Java 使用克鲁斯卡尔求最小生成树(源代码) #### 知识点解析 **克鲁斯卡尔算法概述** 克鲁斯卡尔算法是一种著名的贪心算法,它用于解决无向加权图中的最小生成树问题。所谓最小生成树,是指在一个连通的无向...

    数据结构课程设计----最小生成树

    最小生成树是图论中的一个重要概念,用于解决网络中连接各个顶点的最低成本路径问题。在数据结构课程设计中,构建最小生成树是学习图算法的重要实践环节。本项目包含完整的工程文件和文档,提供了从理论到实现的全面...

Global site tag (gtag.js) - Google Analytics