下面用java实现了图,这个图使用邻接矩阵来实现。然后图的遍历使用了:深度遍历,广度遍历。最小生成树使用普利姆算法以及克鲁斯卡尔算法

package net.itaem.graph;

public class Edge implements Comparable<Edge>{
    private int start;   //起点
    private int end;    //终点
    private int weight = Integer.MAX_VALUE / 2;   //权值,默认为无穷大

    public Edge(int start, int end, int weight){
    	this.start = start;
    	this.end = end;
    	this.weight = weight;
    }

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}

	public int getEnd() {
		return end;
	}

	public void setEnd(int end) {
		this.end = end;
	}

	public int getWeight() {
		return weight;
	}

	public void setWeight(int weight) {
		this.weight = weight;
	}

	@Override
	public String toString() {
		return "Edge [start=" + start + ", end=" + end + ", weight=" + weight
				+ "]";
	}
        //实现了Comparable<Edge>接口,用于排序的时候使用
	@Override
	public int compareTo(Edge that) {
		if(that == this) return 0;

		return this.getWeight() - that.getWeight();
	}

}
package net.itaem.graph;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * 使用邻接矩阵来实现图
 * */
public class Graph {

	private List<String> vexList;

	private List<Edge> edgeList;

	private int[][] edgeArray;

	private boolean[] visited;
	//创建一个图
	public Graph(int size){
		this.vexList = new ArrayList<String>();
		this.edgeList = new ArrayList<Edge>();
		this.edgeArray = new int[size][size];

		for(int i=0; i<size; i++){
			for(int j=0; j<size; j++){
				edgeArray[i][j] = Integer.MAX_VALUE / 2;
			}
		}
		createGraph();
	}

	public boolean isEdgeExists(int start, int end){

		if(edgeArray[start][end] != Integer.MAX_VALUE/2){
			return true;
		}else{
			return false;
		}
	}

	private void createGraph(){
		vexList.add("V0");
		vexList.add("V1");
		vexList.add("V2");
		vexList.add("V3");
		vexList.add("V4");
		vexList.add("V5");
		vexList.add("V6");
		vexList.add("V7");
		vexList.add("V8");

		//初始化4条边,因为是无向边,所以都是成对出现
		Edge edge1 = new Edge(0, 1, 10);
		Edge edge2 = new Edge(0, 5, 11);

		Edge edge3 = new Edge(1, 0, 10);
		Edge edge4 = new Edge(5, 0, 11);

		Edge edge5 = new Edge(1, 2, 18);
		Edge edge6 = new Edge(1, 6, 16);
		Edge edge7 = new Edge(1, 8, 12);

		Edge edge8 = new Edge(2, 1, 18);
		Edge edge9 = new Edge(6, 1, 16);
		Edge edge10 = new Edge(8, 1, 12);

		Edge edge11 = new Edge(2, 3, 22);
		Edge edge12 = new Edge(2, 8, 8);
		Edge edge13 = new Edge(3, 2, 22);
		Edge edge14 = new Edge(8, 2, 8);

		Edge edge15 = new Edge(3, 4, 20);
		Edge edge16 = new Edge(3, 7, 16);
		Edge edge17 = new Edge(3, 8, 21);

		Edge edge18 = new Edge(4, 3, 20);
		Edge edge19 = new Edge(7, 3, 16);
		Edge edge20 = new Edge(8, 3, 21);

		Edge edge21 = new Edge(4, 5, 26);
		Edge edge22 = new Edge(4, 7, 7);

		Edge edge23 = new Edge(5, 4, 26);
		Edge edge24 = new Edge(7, 4, 7);

		Edge edge25 = new Edge(5, 6, 17);
		Edge edge26 = new Edge(6, 5, 17);

		Edge edge27 = new Edge(6, 7, 19);
		Edge edge28 = new Edge(7, 6, 19);

		Edge edge29 = new Edge(1, 8, 12);
		Edge edge30 = new Edge(8, 1, 12);

		add(edge29);
		add(edge30);

		add(edge1);
		add(edge2);
		add(edge3);
		add(edge4);
		add(edge5);
		add(edge6);
		add(edge7);
		add(edge8);
		add(edge9);
		add(edge10);
		add(edge11);
		add(edge12);
		add(edge13);
		add(edge14);
		add(edge15);
		add(edge16);
		add(edge17);
		add(edge18);
		add(edge19);
		add(edge20);
		add(edge21);
		add(edge22);
		add(edge23);
		add(edge24);
		add(edge25);
		add(edge26);
		add(edge27);
		add(edge28);
	}

	public void add(Edge edge){
		for(int i=0; i<vexList.size(); i++){
			for(int j=0; j<vexList.size(); j++){
				//设置这个权值到数组中
				if(i != j && i == edge.getStart() && j == edge.getEnd() && edgeArray[i][j] == Integer.MAX_VALUE/2){
					edgeArray[i][j] = edge.getWeight();
				}else if(i == j){
					edgeArray[i][j] = 0;
				}
			}
		}

		edgeList.add(edge);
	}

	public String toString(){
		StringBuilder sb = new StringBuilder();
		for(int i=0; i<vexList.size(); i++){
			for(int j=0; j<vexList.size(); j++){
				if(edgeArray[i][j] != Integer.MAX_VALUE/2)
					sb.append(edgeArray[i][j]+ " ");
				else
					sb.append("00" + " ");
			}
			sb.append("\n");
		}

		return sb.toString();
	}

	public static void main(String[] args) {
		Graph graph = new Graph(9);
		System.out.println(graph);
		System.out.println("DFS======================================");
		graph.DFS();
		System.out.println("======================================DFS");

		System.out.println();

		System.out.println("BFS======================================");
		graph.BFS();
		System.out.println("end======================================BFS");

		System.out.println("=======minSpanTreePrim==================");
		graph.minSpanTreePrim();
		System.out.println("=======minSpanTreePrim==================");

		System.out.println("=======miniSpanTreeKruskal==================");
		graph.miniSpanTreeKruskal();
		System.out.println("=======miniSpanTreeKruskal==================");

	}

	//深度优先遍历这个图
	public void DFS(){
		visited = new boolean[vexList.size()];  //标识每个节点是否被访问,这里全部重置
		for(int i=0; i<vexList.size(); i++){
			if(!visited[i]){
				DFS0(i);
			}
		}
	}

	public void DFS0(int index){

		System.out.println("vex "+ index +" value is " + vexList.get(index));   //输出这个节点,也可以更换成其它操作

		visited[index] = true;   //设置该节点已经被访问过了

		for(int j=0; j<vexList.size(); j++){
			if(isEdgeExists(index, j) && !visited[j]){
				DFS0(j);
			}
		}
	}

	//广度优先,遍历这个图
	public void BFS(){
		visited = new boolean[vexList.size()];  //标识每个节点是否被访问,这里全部重置

		LinkedList<Integer> queue = new LinkedList<Integer>();

		for(int i=0; i<vexList.size(); i++){
			//如果这个节点没有被访问过,就访问
			if(!visited[i]){
				visited[i] = true;

				System.out.println("vex " + i + " is " + vexList.get(i));     //输出这个节点,也可以更换成其它操作

				queue.addLast(i);   //将这个节点i加入队列

				while(!queue.isEmpty()){
					int index = queue.removeFirst();   //出队列,并且将这个下标记住

					for(int j=0; j<vexList.size(); j++){
						if(isEdgeExists(index, j) && !visited[j]){
							visited[j] = true;
							System.out.println("vex " + j + " is " + vexList.get(j));  //输出这个节点,也可以更换成其它操作
							queue.addLast(j);
						}
					}
				}
			}else{
				//System.out.println(i + " vex is visited");
			}
		}
	}

	/**
	 * 最小生成树,普利姆算法
	 * 出发点:从其中一个顶点出发
	 * 前提条件:无
	 *
	 * */
	public void minSpanTreePrim(){
		int min = 0, i = 0, j = 0, k = 0;
		int[] adjvex = new int[vexList.size()];   //保存顶点相关下标
		int[] lowcost = new int[vexList.size()];   //保存定点之间的权值

		lowcost[0] = 0;   //初始化第一个权值为0,也就是V0加入生成树
		adjvex[0] = 0;    //初始化顶一个定点下标为0

		for(i=1; i<vexList.size(); i++){   //循环其它的定点
			lowcost[i] = edgeArray[0][i];   //取出V0连的边的全部权值

			adjvex[i] = 0;   //初始化都为V0下标
		}

		for(i=1; i<vexList.size(); i++){
			min = Integer.MAX_VALUE / 2;   //初始化权值最小为无穷大
			j = 1;
			k = 0;

			while(j < vexList.size()){
				if(lowcost[j] != 0 && lowcost[j] < min){   //如果权值不为0并且小于MIN,也就是该节点相连的边中最小权值
					min = lowcost[j];
					k = j;   //让最小的值的下标存入k
				}
				j++;
			}

			System.out.println("(" + adjvex[k] + "," + k + ")");   //输出边

			lowcost[k] = 0;   //将当前顶点的权值设置为0,表示此顶点已经完成任务

			for(j = 1; j<vexList.size(); j++){
				if(lowcost[j] != 0 && edgeArray[k][j] < lowcost[j]){
					lowcost[j] = edgeArray[k][j];

					adjvex[j] = k;
				}
			}
		}
	}

	/**
	 * 库鲁斯卡尔算法
	 * 出发点:从边出发
	 *
	 * 前提:这些变都按照权值大小排序好
	 *
	 * 从图的每一条边出发,然后查看这条边是否形成环,如果没有,加入到最小生成树
	 *
	 * */
	public void miniSpanTreeKruskal(){
		int n = 0, m = 0, i = 0;

		int[] parent = new int[vexList.size()];   //定义一个数组用来判断是否形成环路,初始化的值都为0

		//获得排序好的所有边集合,也就是前提条件
		Collections.sort(edgeList);
		Edge[] edges = new Edge[edgeList.size()/2];
		int index = 0;
		for(int j=0; j < edgeList.size(); j++){
			if(j % 2 == 0){
				edges[index++] = edgeList.get(j);
			}
		}

		//循环每一条边
		for(i=0; i<edges.length; i++){

			n = find(parent, edges[i].getStart());   //找到这条边的起点
			m = find(parent, edges[i].getEnd());   //找到这条边的终点

            //如果没有形成环,加入到最小生成树
			if(n != m){   //如果不相等,说明没有构成环
				parent[n] = m;    //将此边的结尾顶点放入到下边起点的parent中,表示此顶点已经在生成树中
				System.out.println("(" + edges[i].getStart() + "," + edges[i].getEnd() + ")" + " weight " + edges[i].getWeight());
			}
		}

	}

	private int find(int[] parent, int f){  //查找连线节点的尾部下标
		while(parent[f] > 0)
			f = parent[f];

		return f;
	}
}

下面是是输出结果

0 10 00 00 00 11 00 00 00
10 0 18 00 00 00 16 00 12
00 18 0 22 00 00 00 00 8
00 00 22 0 20 00 00 16 21
00 00 00 20 0 26 00 7 00
11 00 00 00 26 0 17 00 00
00 16 00 00 00 17 0 19 00
00 00 00 16 7 00 19 0 00
00 12 8 21 00 00 00 00 0 

DFS======================================
vex 0 value is V0
vex 1 value is V1
vex 2 value is V2
vex 3 value is V3
vex 4 value is V4
vex 5 value is V5
vex 6 value is V6
vex 7 value is V7
vex 8 value is V8
======================================DFS

BFS======================================
vex 0 is V0
vex 1 is V1
vex 5 is V5
vex 2 is V2
vex 6 is V6
vex 8 is V8
vex 4 is V4
vex 3 is V3
vex 7 is V7
end======================================BFS
=======minSpanTreePrim==================
(0,1)
(0,5)
(1,8)
(8,2)
(1,6)
(6,7)
(7,4)
(7,3)
=======minSpanTreePrim==================
=======miniSpanTreeKruskal==================
(4,7) weight 7
(2,8) weight 8
(0,1) weight 10
(0,5) weight 11
(1,8) weight 12
(1,6) weight 16
(3,7) weight 16
(6,7) weight 19
=======miniSpanTreeKruskal==================

时间: 2024-10-22 19:44:33

图的相关文章

利用filter实时切换big5和gb2312,以及gb2312的简繁体

IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 Stack Overflow.Twitter.Reddit.IEEE Xplore.GitHub.CareerBuilder 等,对 48 种语言进行排行. 与其他排行榜不同的是,IEEE Spectrum 可以让读者自己选择参数组合时的权重,得到不同的排序结果.考虑到典型的 Spectrum 读者需求

俑烟汲的诿樟透磺勒秤窗mvus

IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 Stack Overflow.Twitter.Reddit.IEEE Xplore.GitHub.CareerBuilder 等,对 48 种语言进行排行. 与其他排行榜不同的是,IEEE Spectrum 可以让读者自己选择参数组合时的权重,得到不同的排序结果.考虑到典型的 Spectrum 读者需求

时序图与状态图(Rose) - Windows XP经典软件系列

最近开始了自己高级数据结构之旅,在这次旅行中,我将持续把一些高级的数据结构从理论到编码都过一遍,同时通过博客形式分享出来,希望大家指出不足之处! 二叉排序树是一种动态排序的数据结构,支持插入.删除.查找等操作,且平均时间复杂度为O(log(N)),但是普通二叉排序树不能保证树退化为一颗分支的情况,此时最坏情况下的时间复杂度为O(N).此时,平衡二叉树的产生了.平衡二叉树是一种动态调整平衡的数据结构,但理想的平衡二叉树很难,于是人们使用AVL.红黑树.Treap.伸展树等来替代平衡二叉树,这些数据

类图(Rose) - Windows XP经典软件系列

最近开始了自己高级数据结构之旅,在这次旅行中,我将持续把一些高级的数据结构从理论到编码都过一遍,同时通过博客形式分享出来,希望大家指出不足之处! 二叉排序树是一种动态排序的数据结构,支持插入.删除.查找等操作,且平均时间复杂度为O(log(N)),但是普通二叉排序树不能保证树退化为一颗分支的情况,此时最坏情况下的时间复杂度为O(N).此时,平衡二叉树的产生了.平衡二叉树是一种动态调整平衡的数据结构,但理想的平衡二叉树很难,于是人们使用AVL.红黑树.Treap.伸展树等来替代平衡二叉树,这些数据

一张图掌握移动Web前端所有技术(大前端、工程化、预编译、自动化)

你要的移动web前端都在这里! 大前端方向:移动Web前端.Native客户端.Node.js. 大前端框架:React.Vue.js.Koa 跨终端技术:HTML 5.CSS 3.JavaScript 跨平台框架:React Native.Cordova 前端工程化:Grunt.Gulp.Webpack 前端预编译:Babel.Sass.Less 自动化测试:Jasmine.Mocha.Karma 一图在手,应有尽有! 更多信息参考:https://item.jd.com/12170351.h

Java企业微信开发_08_JSSDK多图上传

一.本节要点 1.1可信域名 所有的JS接口只能在企业微信应用的可信域名下调用(包括子域名),可在企业微信的管理后台“我的应用”里设置应用可信域名.这个域名必须要通过ICP备案,不然jssdk会配置失败 1.2JS-SDK使用权限签名算法 1.2.1 签名生成规则如下: (1)参与签名的字段包括: noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) . (2)对所有待签名参数按照字段名的ASCII

以JPanel为基础实现一个图相框

代码: import java.awt.Graphics; import javax.swing.ImageIcon; import javax.swing.JPanel; public class Picture extends JPanel { private static final long serialVersionUID = -4437881316229152596L; private ImageIcon icon; public Picture(java.net.URL imgUR

jQuery----无缝轮播图

1.效果 2.html代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <link rel="stylesheet" type="text/css" href="css/iconfont.css"> <link rel="stylesh

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

Android自己定义控件之轮播图控件

背景 近期要做一个轮播图的效果.网上看了几篇文章.基本上都能找到实现,效果还挺不错,可是在写的时候感觉每次都要单独去又一次在Activity里写一堆代码.于是自己封装了一下.这里仅仅是做了下封装成一个控件,不必每次反复写代码了. 效果图 实现分析 轮播图的功能就是实现左右滑动的广告.图片信息展示,那我们就用ViewPager来实现,由于考虑到用户体验,我们还须要在以下加一个指示器来标示滑动到了第几张轮播图.指示器我们能够用一个线性布局来依据要展示的轮播图设置显示的View,我们要做这种一个控件没