个人学习图论小计

57 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

图的常用概念

无向图顶点之间没有任何方向比如可以a-b也可以b-a 有向图有固定的链接方向就是有向图 带权图边带有权值的图也叫网 在这里插入图片描述

邻接矩阵 用二维数组表示0代表不链接 1代表有链接

用邻居接矩阵可能会造成空间的浪费在这里插入图片描述 邻接表 他由数组加链表组成 在这里插入图片描述

完整代码展示

package name;

import java.math.BigInteger;
import java.util.*;

public class lanqiao {
	private ArrayList<String>arr;//定义顶点集合也就是他的名字
	private int [][]edgs;//邻接矩阵
	private int numberof;//表示多少条边 个数数目
	public static void main(String[] args) {
		//测试图
		int n=5;//节点的个数
		String s1[]= {"A","B","C","D","E"};
		//创建图对象
		lanqiao graph = new lanqiao(n);
		//循环添加顶点
		for(String value:s1) {
			graph.index(value);//添加值顶点
		}
		//添加边如果不添加边数据是全0的
	//	A-B A-C B-C B-D B-E
		graph.insetag(0, 1, 1);//ab
		graph.insetag(0, 2, 1);//ac
		graph.insetag(1, 2, 1);//bc
		graph.insetag(1, 3, 1);//bd
		graph.insetag(1, 4, 1);//be
		//显示链接矩阵
		graph.showGret();
		System.out.println();
	}
	//写一个构造器
	public lanqiao(int n) {
		//初始化矩阵和边
		edgs=new int [n][n];
		arr=new ArrayList<String>(n);
		numberof=0;//他的边默认为0
	}
	//插入节点也就是插入顶点
	public void index(String s1) {//插入顶点传入的就是顶点的字符串
		arr.add(s1);//插入节点
		
	}
	//图中常用方法
	//返回图结点的个数
	public int getNumber() {
		return arr.size();//节点个数也就是数组长度
	}
	//得到边的数目
	public int getNumberof() {
		return numberof;
	}
	//返回节点i(下标)对应的数据 0返回A 1返回B 2 返回 C根据节点的添加顺序有关
	public  String getValue(int i) {
		return arr.get(i); 
	}
	//返回v1和v2的权
	public int getWeight(int v1,int v2) {
		return edgs[v1][v2];//这个方法返回权值
	}
	public void showGret() {//返回图的这个矩阵
		for(int [] link:edgs) {
			System.out.println(Arrays.toString(link));
		}
		
	}
	
	//添加边通过矩阵来描述他们的边
	//权值weigth 权值就是边对应的值要么是1要么是0 默认是
	public void insetag(int v1,int v2,int weigth) {
		//v1代表数组里面的A-B之间A和B的链接是0还是1
		//v2表示指定里面的第几个元素比如是C那么v2就是3
		//权值表示他们是关联的0或1
		edgs[v1][v2]=weigth;
		edgs[v2][v1]=weigth;//因为是无向图所以反过来一编
		numberof++;//边+1
	}
}



图论dfs 1.先找到第一个初始节点,然后把经历过的节点都标记已访问 2.查找节点的第一个邻接节点 3.如果w节点存在执行4 如果代码不存在返回最初的节点继续往下走 4.如果w节点未被访问那么对w进行深度优先遍历可以把w当作另一个v然后进行步骤重新123 5.查找节点w的邻接节点的下一个节点转到步骤3

package Graph;

import java.nio.Buffer;
import java.util.*;

public class Graph {

	private ArrayList<String> arr;// 定义顶点集合也就是他的名字
	private int[][] edgs;// 邻接矩阵
	private int numberof;// 表示多少条边 个数数目
	private boolean[] isVisti;

	public static void main(String[] args) {
		// 测试图
		int n = 5;// 节点的个数
		String s1[] = { "A", "B", "C", "D", "E" };
		// 创建图对象
		Graph graph = new Graph(n);
		// 循环添加顶点
		for (String value : s1) {
			graph.index(value);// 添加值顶点
		}
		// 添加边如果不添加边数据是全0的
		// A-B A-C B-C B-D B-E
		graph.insetag(0, 1, 1);// ab
		graph.insetag(0, 2, 1);// ac
		graph.insetag(1, 2, 1);// bc
		graph.insetag(1, 3, 1);// bd
		graph.insetag(1, 4, 1);// be
		// 显示链接矩阵
		graph.showGret();
		System.out.println();
		graph.dfs();
	}

	// 写一个构造器
	public Graph(int n) {
		// 初始化矩阵和边
		isVisti = new boolean[5];
		edgs = new int[n][n];
		arr = new ArrayList<String>(n);
		numberof = 0;// 他的边默认为0
	}

	// 得到第一个邻接结点的下标
	public int getFir(int index) {
		for (int j = 0; j < arr.size(); j++) {
			if (edgs[index][j] > 0) {
				return j;
				// 如果他的旁边有节点就返回节点
				// 否则返回-1
			}

		}
		return -1;
	}

	// 根据前一个邻接节点的下标获取下一个邻接节点
	public int getNext(int v1, int v2) {
		for (int j = v2 + 1; j < arr.size(); j++) {
			if (edgs[v1][j] > 0) {
				return j;
			}
		}
		// v1 是当前节点 v1是邻接节点
		return -1;
	}

	// dfs
	// i第一次就是0
	public void dfs(boolean[] isVisited, int i) {
		System.out.println(getValue(i) + ">");
		// 把访问过的节点设置为已经访问过了
		isVisited[i] = true;
		int w = getFir(i);// 查找节点i的第一个邻接节点
		while (w != -1) {
			if (!isVisited[w]) {// 判断他是否被访问过
				dfs(isVisited, w);
			}
			// 如果w节点已经被访问过
			w = getNext(i, w);// i正在访问的节点

		}
	}

	// dfs 进行重载遍历所有的节点进入dfs
	public void dfs() {
		// 遍历所有的节点,进行dfs回溯
		for (int i = 0; i < getNumber(); i++) {
			if (!isVisti[i]) {
				dfs(isVisti, i);
			}
		}
	}

	// 插入节点也就是插入顶点
	public void index(String s1) {// 插入顶点传入的就是顶点的字符串
		arr.add(s1);// 插入节点

	}

	// 图中常用方法
	// 返回图结点的个数
	public int getNumber() {
		return arr.size();// 节点个数也就是数组长度
	}

	// 得到边的数目
	public int getNumberof() {
		return numberof;
	}

	// 返回节点i(下标)对应的数据 0返回A 1返回B 2 返回 C根据节点的添加顺序有关
	public String getValue(int i) {
		return arr.get(i);
	}

	// 返回v1和v2的权
	public int getWeight(int v1, int v2) {
		return edgs[v1][v2];// 这个方法返回权值
	}

	public void showGret() {// 返回图的这个矩阵
		for (int[] link : edgs) {
			System.out.println(Arrays.toString(link));
		}

	}

	// 添加边通过矩阵来描述他们的边
	// 权值weigth 权值就是边对应的值要么是1要么是0 默认是
	public void insetag(int v1, int v2, int weigth) {
		// v1代表数组里面的A-B之间A和B的链接是0还是1
		// v2表示指定里面的第几个元素比如是C那么v2就是3
		// 权值表示他们是关联的0或1
		edgs[v1][v2] = weigth;
		edgs[v2][v1] = weigth;// 因为是无向图所以反过来一编
		numberof++;// 边+1
	}

}