图的所有简单算法实现

包括邻接链表、有向无向图、带权图、增删顶点和边、查找、连通、DFS和BFS等。这只是一个最初版本,有些复杂的算法还没有实现。

package structure;
//图的邻接链表的节点
public class GraphListNode {

	private int vertex;//图的顶点
	private int weight;//边的权重
	private boolean visited;//是否访问过

	//带权重图的节点
	public GraphListNode(int vertex,int weight){
		this.vertex = vertex;
		this.weight = weight;
		this.visited = false;//默认为未访问
	}

	public boolean isVisited() {
		return visited;
	}

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

	public int getVertex() {
		return vertex;
	}
	public void setVertex(int vertex) {
		this.vertex = vertex;
	}
	public int getWeight() {
		return weight;
	}
	public void setWeight(int weight) {
		this.weight = weight;
	}	

}

下面就是图的实现了,还有测试代码

package structure;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

//邻接链表表示的图
public class AdjacencyListGraph {

	private LinkedList<LinkedList<GraphListNode>> vertexList;//点链表

	public LinkedList<LinkedList<GraphListNode>> getVertexList() {
		return vertexList;
	}

	//图中是否包含某个顶点
	public boolean contains(int vertex){
		Iterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()) {
			//如果当前顶点的边链表已经存在,直接返回
			if (itr.next().get(0).getVertex() == vertex) {
				return true;
			}
		}
		return false;
	}

	public AdjacencyListGraph(){
		this.vertexList = new LinkedList<LinkedList<GraphListNode>>();
	}

	//增加一个顶点
	public void addVertexSingle(int vertexNo){

		if (contains(vertexNo)) {
			return;
		}

		//定义一个以vertexNo为头的边链表
		LinkedList<GraphListNode> ll = new LinkedList<GraphListNode>();
		ll.add(new GraphListNode(vertexNo,0));
		//将边链表加入到点链表中
		vertexList.add(ll);
	}

	//单向删除一个顶点
	public void deleteVertexSingle(int vertexNo){
		Iterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()) {
			//找到相应点对应的边链表,删除
			LinkedList<GraphListNode> ll = itr.next();
			if (ll.get(0).getVertex() == vertexNo) {
				itr.remove();
				break;
			}
		}
	}

	//双向删除一个顶点
	public void deleteVertexDouble(int vertexNo){
		Iterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()) {
			//找到相应点对应的边链表,删除
			LinkedList<GraphListNode> ll = itr.next();
			if (ll.get(0).getVertex() == vertexNo) {
				itr.remove();
				break;
			}
		}
		itr = vertexList.listIterator();
		//删除所有的相关记录
		while(itr.hasNext()){
			LinkedList<GraphListNode> ll = itr.next();
			Iterator<GraphListNode> li = ll.listIterator();
			while (li.hasNext()) {
				if (li.next().getVertex() == vertexNo) {
					li.remove();
				}
			}
		}
	}

	//双向增加
	public void addEdgeDouble(int vertexNoU,int vertexNoV){
		addEdgeDouble(vertexNoU, vertexNoV, 0);
	}

	public void addEdgeDouble(int vertexNoU,int vertexNoV,int weight){
		updateEdge(vertexNoU, vertexNoV, weight);
		updateEdge(vertexNoV, vertexNoU, weight);
	}

	//增加一个不带权重的从u到v的边
	public void addEdgeSingle(int vertexNoU,int vertexNoV){
		updateEdge(vertexNoU, vertexNoV,0);
	}

	public void addEdgeSingle(int vertexNoU,int vertexNoV,int weight){
		updateEdge(vertexNoU, vertexNoV,weight);
	}

	//增加或修改一条从u到v,权重为weight的边
	public void updateEdge(int vertexNoU,int vertexNoV,int weight){

		Iterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()) {
			//检测以vertexNoU为顶点的边链表是否存在
			LinkedList<GraphListNode> ll  = itr.next();
			if (ll.get(0).getVertex() == vertexNoU) {
				//检测在该边链表中是否已经存在从u到v的边
				Iterator<GraphListNode> it = ll.listIterator();
				while (it.hasNext()) {
					if (it.next().getVertex() == vertexNoV) {
						//如果已经存在该边,直接更新权重
						it.next().setWeight(weight);
						return;
					}
				}
				//如果不存在该边,则增加该边
				ll.add(new GraphListNode(vertexNoV, weight));
				return;
			}
		}
		//如果不存在顶点vertexNoU,增加顶点U,然后增加边uv
		addVertexSingle(vertexNoU);
		updateEdge(vertexNoU, vertexNoV, weight);
	}

	//双向设置标记
	public void setMarkDouble(int vertexNo,boolean flag){
		ListIterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()){
			LinkedList<GraphListNode> ll = itr.next();
			for (GraphListNode gln: ll) {
				if (gln.getVertex() == vertexNo) {
					gln.setVisited(flag);
				}
			}
		}
	}

	//在进行遍历前,清除所有标记
	public void clearAllMark(){
		ListIterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()){
			LinkedList<GraphListNode> ll = itr.next();
			for (GraphListNode gln: ll) {
				gln.setVisited(false);
			}
		}

	}

	public void DFS(int startVertex){
		clearAllMark();
		depthFirstSearch(startVertex);
	}

	//深度优先搜索
	public void depthFirstSearch(int startVertex){

		boolean isExisted = false;
		ListIterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()) {
			//检测以startVertex为顶点的边链表是否存在
			LinkedList<GraphListNode> ll  = itr.next();
			if (ll.get(0).getVertex() == startVertex) {
				isExisted = true;
				//进行深度优先搜索
				Iterator<GraphListNode> it= ll.listIterator();

				//跳过第一个顶点并设置第一个顶点为以遍历
				System.out.print(startVertex+" ");
				GraphListNode gln = it.next();
				setMarkDouble(startVertex, true);

				while (it.hasNext()) {
					gln = it.next();
					//如果未访问,则进行深度搜索
					if (!gln.isVisited()) {
						depthFirstSearch(gln.getVertex());
						setMarkDouble(gln.getVertex(), true);
					}	

				}

				break;
			}
		}
		if (!isExisted) {
			System.out.println(startVertex+" is not exists in this graph");
		}
	}

	public void BFS(int startVertex){
		clearAllMark();
		breadthFirstSearch(startVertex);
	}

	//广度优先搜索
	public void breadthFirstSearch(int startVertex){
		boolean isExisted = false;
		ListIterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		//使用链表模仿队列
		LinkedList<Integer> store = new LinkedList<Integer>();
		isExisted = contains(startVertex);
		if (!isExisted) {
			System.out.println(startVertex+" is not exists in this graph");
		}
		//进行广度优先搜索
		else {

			//压入队列并设置为已遍历,初始化队列
			store.offer(startVertex);
			setMarkDouble(startVertex, true);

			while (!store.isEmpty()) {
				int current = store.poll();
				//打印当前顶点
				System.out.print(current+" ");
				//找出当前顶点对应的边链表
				itr = vertexList.listIterator();
				while(itr.hasNext()) {
					LinkedList<GraphListNode> ll  = itr.next();
					if (ll.get(0).getVertex() == current) {
						Iterator<GraphListNode> it = ll.listIterator();
						//跳过第一个
						it.next();
						while (it.hasNext()) {
							//将该顶点的所有相邻顶点压入队列
							GraphListNode gln = it.next();
							if (!gln.isVisited()) {
								store.offer(gln.getVertex());
								setMarkDouble(gln.getVertex(), true);
							}
						}
					}
				}
			}
		}
	}

	//判断两个点是否联通
	//这里由于程序的限制,测试中一般只能测试是否直接相连
	public boolean isConnected(int src,int des){
		//递归终止条件

		Iterator<LinkedList<GraphListNode>> itr = vertexList.listIterator();
		while(itr.hasNext()) {
			//找到点U
			LinkedList<GraphListNode> ll = itr.next();
			if (ll.get(0).getVertex() == src) {
				Iterator<GraphListNode> it = ll.listIterator();
				//跳过它自身
				it.next();
				while (it.hasNext()) {
					src = it.next().getVertex();
					if (src == des) {
						return true;
					}
					//恢复迭代器
					itr = vertexList.listIterator();
				}
			}
		}
		return false;

	}

	//打印邻接链表
	public void printAllLinkedlist(){
		for (LinkedList<GraphListNode> ll : vertexList) {
			for (GraphListNode gln : ll) {
				//权重为0则不打印
				if (gln.getWeight() == 0) {
					System.out.print(gln.getVertex()+" ");
				}
				else{
					System.out.print(gln.getVertex()+"("+gln.getWeight()+") ");
				}
			}
			System.out.println();
		}
	}

	/**
	 * Kuruskal算法:根据边找出最小生成树
	 * Prim算法:根据点找出最下生成树
	 * Dijkstra算法:每次处理一个顶点,最终得到从某一顶点到所有其他顶点的最短路径
	 * 省略
	 * */	

	public static void main(String[] args) {
		//建立一个无向图
/*		AdjacencyListGraph alg = new AdjacencyListGraph();

		alg.addEdgeDouble(1,3);
		alg.addEdgeDouble(1,5);
		alg.addEdgeDouble(2,3);
		alg.addEdgeDouble(2,6);
		alg.addEdgeDouble(3,4);
		alg.addEdgeDouble(3,6);
		alg.addEdgeDouble(5,6);
		alg.addEdgeDouble(7, 4);

		alg.printAllLinkedlist();
		System.out.println("--------------");
	    alg.deleteVertexDouble(1);
		alg.printAllLinkedlist();
		System.out.println("--------------");
		alg.addVertexSingle(1);
		alg.addEdgeDouble(1, 3);
		alg.addEdgeDouble(1, 5);
		alg.printAllLinkedlist();
		System.out.println("--------------");

		alg.DFS(1);
		System.out.println("\n--------------");
		alg.BFS(1);

		//System.out.println(alg.isConnected(1, 4));

		//增加有向边,并设置权重
		alg.addEdgeSingle(1,2,10);
		alg.addEdgeSingle(1,3,3);
		alg.addEdgeSingle(1,4,20);
		alg.addEdgeSingle(3,2,2);
		alg.addEdgeSingle(2,4,5);
		alg.addEdgeSingle(3,5,15);
		alg.addEdgeSingle(4,5,11);
		alg.printAllLinkedlist();
*/			

	}
}

图的所有简单算法实现,布布扣,bubuko.com

时间: 2024-10-28 08:39:42

图的所有简单算法实现的相关文章

hdu 4858 项目管理 图分治 (复合算法)

hdu 4858 项目管理 题意:给n(<=100000)个点,m条边( <=n+10),可能有重边,每个点有个值val,初识为0. 2种操作. 操作1:点x的值,加addx. 操作2:输出x点的邻点的val和. 分析:简单的优化操作1或操作2是不行的. 法一:针对点的度将图中点分为两类点.对于度大于sqrt (n)的点为重点,对于小于等于sqrt(n)的点为轻点. 重点的个数小于sqrt(n)个.针对重点和轻点分别处理. 法二:也可考虑每个点,将其邻点分类.大于该点度的点分为一类,等于该点的

图的最小生成树——Kruskal算法

Kruskal算法 图的最小生成树的算法之一,运用并查集思想来求出最小生成树. 基本思路就是把所有边从小到大排序,依次遍历这些边.如果这条边所连接的两个点在一个连通块里,遍历下一条边,如果不在,就把这条边加入连通块,这样就可以保证生成树的边权最小. 我们使用并查集来判断两个点是否在同一个连通块里,如果在,他们的find会相同,否则不在. 1 #include<cstdio> 2 #include<algorithm> 3 #define N 42000 4 using namesp

Android图表库MPAndroidChart(七)—饼状图可以再简单一点

Android图表库MPAndroidChart(七)-饼状图可以再简单一点 接上文,今天实现的是用的很多的,作用在统计上的饼状图,我们看下今天的效果 这个效果,我们实现,和之前一样的套路,我先来说下这个的应用场景,假设,我是一名小学老师,现在教务处让我设置一个图表,说明下我带的班级期末考试有多少人优秀,多少人及格和不及格等等,而这些呢,我已经算出来百分比了,只剩下画图了,那好,我们就来实现以下吧 一.基本实现 首先是我们的布局 <com.github.mikephil.charting.cha

任性动图--傻瓜式创作动图、创作动图就是这么简单、就是这么任性!!!

作者:www.gudianxiaoshuo.com 傻瓜式创作动图.创作动图就是这么简单.就是这么任性!!! 任性动图能做什么? 1  文字.诗词生成动图 任性横竖写文字 任性设置运动和时间 2 照片添加文字.生成动图 拖入背景照片,便可编辑生成动图 也可多张照片合成动图 3 动图修改.添加文字 拖入动图背景,对其编辑修改 4 出屏动图制作 使用出屏条功能,更容易将原有动图创作为出屏动图 5 微博动图 有时动图的尺寸过大,发到微博上 是不动的 任性动图也支持将大图生成可在微博运动小动图 由任性动

根据权重挑选通道的简单算法

当存在一批通道,根据权重,选择哪个通道去使用的简单算法. 利用随机数,数据区间,来获取通道. 通道权重越大,单位时间内使用该通道的概率会大一些. 代码 1 //利用了一个权重区间的比例问题,抓取随机数的可能性,来体现权重思想 2 public static void main(String[] args) { 3 //定义三个通道的权重,按随机数选拔使用哪个通道. 4 //A 10 B 70 C 30 5 //从数据库查询出list集合 6 ChannelD A=new ChannelD("A&

数据结构--图--最小生成树(Prim算法)

构造连通网的最小生成树,就是使生成树的边的权值之和最小化.常用的有Prim和Kruskal算法.先看Prim算法:假设N={V,{E}}是连通网,TE是N上最小生成树中边的集合.算法从U={u0}(uo属于V),TE={}开始,重复执行下述操作:在所有u属于U,v属于V-U的边(u,v)属于E中找到代价最小的一条边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止.此时TE中必有n-1条边,T={V,{TE}}为N的最小生成树.为实现此算法,需另设一个辅助数组closedge,以记录从U

JS 简单算法

//分别使用while/do-while/for循环实现10的阶乘(使用递归算法) //do-while循环实现10的阶乘 var i=1; var resule=1; do{ resule *= i; i++; }while(i0;i--){ if(a%i == 0 && b%i == 0){ console.log(i); break; } } //for循环求最小公倍数 for(var i=max;ib){ min = b; max = a; }else{ min = a; max

【线性表基础】基于线性表的简单算法【Java版】

本文描述了基于线性表的简单算法及其代码[Java实现] 1-1 删除单链表中所有重复元素 // Example 1-1 删除单链表中所有重复元素 private static void removeRepeat(LinkList L) { Node node = L.head.next; // 首结点 while (node != null) // 一重循环,遍历L中的每一个元素 { // Object data=p.data; Node p = node; // q结点的前驱 Node q =

【华为云技术分享】灰度图二值化算法

[摘要] 目前最常用的快速二值化阈值确定方法为根据每一张目标图像来动态的计算平均灰度值.然后将灰度图像中的每个像素灰度值和此平均阈值作对比,高于平均阈值的记为“1”(白色),低于的则设置为“0”(黑色).这种方法虽然会让造成部分背景像素点丢失,但却是最简单高效的处理方法. 灰度图片中都可以用一个具体的灰度值Grav来量化每一个像素点.考虑到实际识别的二值特征,为了让被处理目标答题卡更加简单,计算量更少,速度更快,我们可以直接对灰度图片进行二值化处理. 图像二值化简单来说就是讲整个灰度图片的目标像