一、图的基本概念
图是一种和树相像的数据结构,通常有一个固定的形状,由物理或者抽象的问题来觉得。
顶点:就是图中每个数据
邻接:如果两个顶点被同一条边所连接,称这两个顶点是邻接的
路径:路径是从一个顶点到另外一个顶点所经过的边
连通图和非连通图:至少有一条路径可以连接到所有的顶点,那么这个图就是连通图,否则是非连通图,但是非连通图的子图又可以是连通图
有向图和无向图:有向图表示边是有方向的,无向图的边是没有方向的
带权图:在有些图中,边被赋予了一个权值,权值是一个数字,可以是两个顶点间的距离、时间等等,这样的图就叫做带权图。

二、 图的实现
图的实现有两种方式:
• 邻接表:二维链表
• 邻接矩阵:二维数组

邻接矩阵来完成图:

创建顶点类:
/**

  • 顶点
  • @author Administrator

*/

public class Vertex {
	private char label;//顶点名称
	
	public char getLabel() {
		return label;
	}

	public void setLabel(char label) {
		this.label = label;
	}

	public Vertex(char label) {
		this.label = label;
	}
}

创建图操作类:

public class Graph {
	//顶点数组
	private Vertex[] vertexList;
	//邻接矩阵
	private int[][] adjMat;
	//顶点最大数目
	private int maxSize;
	//定义当前的顶点
	private int nVertext;
	
	public Vertex[] getVertexList() {
		return vertexList;
	}

	public void setVertexList(Vertex[] vertexList) {
		this.vertexList = vertexList;
	}

	public int[][] getAdjMat() {
		return adjMat;
	}

	public void setAdjMat(int[][] adjMat) {
		this.adjMat = adjMat;
	}

	public int getMaxSize() {
		return maxSize;
	}

	public void setMaxSize(int maxSize) {
		this.maxSize = maxSize;
	}

	public int getnVertext() {
		return nVertext;
	}

	public void setnVertext(int nVertext) {
		this.nVertext = nVertext;
	}

	public Graph() {
		vertexList = new Vertex[maxSize];
		adjMat = new int[maxSize][maxSize];
		for (int i = 0; i < adjMat.length; i++) {//给邻接矩阵设置初始值
			for (int j = 0; j < adjMat[i].length; j++) {
				adjMat[i][j] = 0;
			}
		}
		nVertext = 0;
	}
	/**
	 * 添加顶点
	 * @param label
	 */
	public void addVertex(char label) {
		vertexList[nVertext++] = new Vertex(label);
	}
	public void addEdga(int start,int end) {
		adjMat[start][end] = 1;
		adjMat[end][start] = 1;
	}
}

测试类:

public class GraphTest {
	public static void main(String[] args) {
		Graph g = new Graph();
		g.addVertex('A');
		g.addVertex('B');
		g.addVertex('C');
		
		g.addEdga(0, 1);
		g.addEdga(0, 2);
		g.addEdga(1, 2);
	}
}

三、 图的搜索
图的搜索是指从一个顶点可以到达哪些顶点,图的搜索可以分为两类:
• 深度优先搜索DFS
• 广度优先搜索BFS

深度优先搜索规则:
• 1,如果可能,访问一个邻接未访问的顶点,标记它并把它放入栈中
• 2,当不能执行规则1时,如果栈不为空,就从栈中弹出一个顶点
• 3,当不能执行规则1和规则2时,就完成对整个图的搜索过程
修改顶点类:
/**

  • 顶点
  • @author Administrator

*/

public class Vertex {
	private char label;//顶点名称
	private boolean isVisited;//是否被访问过
	
	public boolean isVisited() {
		return isVisited;
	}

	public void setVisited(boolean isVisited) {
		this.isVisited = isVisited;
	}

	public char getLabel() {
		return label;
	}

	public void setLabel(char label) {
		this.label = label;
	}

	public Vertex(char label) {
		this.label = label;
		this.isVisited = false;
	}
}

修改图的操作类:

public class Graph {
	//顶点数组
	private Vertex[] vertexList;
	//邻接矩阵
	private int[][] adjMat;
	//顶点最大数目
	private int maxSize = 10;
	//定义当前的顶点
	private int nVertext;
	//栈
	private MyStack stack;
	
	public MyStack getStack() {
		return stack;
	}

	public void setStack(MyStack stack) {
		this.stack = stack;
	}

	public Vertex[] getVertexList() {
		return vertexList;
	}

	public void setVertexList(Vertex[] vertexList) {
		this.vertexList = vertexList;
	}

	public int[][] getAdjMat() {
		return adjMat;
	}

	public void setAdjMat(int[][] adjMat) {
		this.adjMat = adjMat;
	}

	public int getMaxSize() {
		return maxSize;
	}

	public void setMaxSize(int maxSize) {
		this.maxSize = maxSize;
	}

	public int getnVertext() {
		return nVertext;
	}

	public void setnVertext(int nVertext) {
		this.nVertext = nVertext;
	}

	public Graph() {
		vertexList = new Vertex[maxSize];
		adjMat = new int[maxSize][maxSize];
		for (int i = 0; i < adjMat.length; i++) {//给邻接矩阵设置初始值
			for (int j = 0; j < adjMat[i].length; j++) {
				adjMat[i][j] = 0;
			}
		}
		nVertext = 0;
		stack = new MyStack(maxSize);
	}
/**
 * 添加顶点
 * @param label
 */
	public void addVertex(char label) {
		vertexList[nVertext++] = new Vertex(label);
	}
/**
 * 添加边
 * @param start
 * @param end
 */
	public void addEdga(int start,int end) {
		adjMat[start][end] = 1;
		adjMat[end][start] = 1;
	}
/**
 * 获取邻接没有访问过的节点
 */
	public int getVertex(int v) {
		for (int i = 0; i < nVertext; i++) {
			if(adjMat[v][i] == 1 && vertexList[i].isVisited() == false) {//有边相连,并且没有访问过
				return i;
			}
		}
		return -1;
	}
/**
 * 定义搜索方法
 * 
 */
	public void dfs() {
		//首先访问0号节点
		vertexList[0].setVisited(true);
		displayVertex(0);//压入前进行访问
		//压入栈中
		stack.push(0);
		while( ! stack.isEmppty()) {
				//获得一个未访问的节点
			int v = this.getVertex(stack.peek());
			if(v == -1) {
				//弹出一个顶点
				int x = stack.pop();
//				displayVertex(x);//弹出的时候进行访问
				
			}else {
				vertexList[v].setVisited(true);//表示访问
				displayVertex(v);//压入前进行访问
				//压入栈中
				stack.push(v);
			}
		}
		//搜索完成,要将访问标记修改为原始状态
		for (int i = 0; i < nVertext; i++) {
			vertexList[i].setVisited(false);
		}
	}
	public void displayVertex(int v) {
		System.out.println(vertexList[v] .getLabel());//显示节点
	}
}

修改栈:

public class MyStack {
	private int maxSize;
	private int[] arr;
	private int top;//表示栈顶元素的位置
	
	public MyStack(int size) {
		this.maxSize = size;//定义栈的大小
		this.arr = new int[this.maxSize];
		this.top = -1;//表示是一个空栈
	}
	/**
	 * 压入数据
	 * @param value
	 */
	public void push(int value) {
		arr[ ++ top] = value;
	}
	/**
	 * 数据弹出
	 * @return
	 */
	public int pop() {
		return arr[top--];
	}
	/**
	 * 判断栈是否为空
	 * @return
	 */
	public boolean isEmppty() {
		return top == -1;
	}
	/**
	 * 判断栈是否满了
	 * @return
	 */
	public boolean isFull() {
		return top == (maxSize-1);
	}
	public int peek() {
		return arr[top];
	}
}

广度优先搜索原则:
• 访问下一个邻接位访问的顶点,这个顶点必须是当前节点的临界点,标记它,并且将它插入队列
• 如果无法执行1,那么就从对头的取出一个顶点,并使用其作为当前顶点
• 当队列为空不能执行规则2时,就完成整个搜索的过程

借鉴于:https://www.cnblogs.com/g177w/p/8475492.html
以及大学数据结构课程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷偷学习被我发现

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值