【复习笔记】手敲经常忘记的关于图的几个算法

BFS 

类似于树的层次遍历,用队列依次存储节点的孩子节点然后做出队操作。

唯一不同的是树不存在环,但图存在环,所以遍历图的时候需要设置一个访问矩阵,来记录一个节点是否已经被遍历过。

public static void BFS(int [][] graph, int sx){
		int dim = graph.length;
		
		boolean [] visited = new boolean [dim];
		
		LinkedList<Integer> queue = new LinkedList<Integer>();
		for(int i = 0; i < dim; ++i)
			visited[i] = false;
		queue.add(sx);
		while(!queue.isEmpty()){
			int node = queue.remove(0);
			if(!visited[node])System.out.print(node + 1 + " ");
			visited[node] = true;
			for(int i = 0; i < dim; ++i){
				if(graph[node][i] == 1 && !visited[i])
					queue.add(i);
			}
		}
	}

测试数据:邻接矩阵

int [][] graph ={{0,1,0,0,0,0,0,0},
						{1,0,1,1,0,0,0,0},
						{0,1,0,0,1,1,0,0},
						{0,1,0,0,1,0,1,0},
						{0,0,1,1,0,0,0,1},
						{0,0,1,0,0,0,1,0},
						{0,0,0,1,0,1,0,0},
						{0,0,0,0,1,0,0,0}};

求以节点1为起点的遍历结果:1 2 3 4 5 6 7 8


DFS 

类似于二叉树的前序遍历,一直递归到某一节点立即进行遍历,然后选一个孩子继续递归。

DFS的遍历结果不是唯一的。同样需要一个记录矩阵。

public static void DFS(int [][] graph, int sx){
		int dim = graph.length;
		
		boolean [] visited = new boolean [dim];
		for(int i = 0; i < dim; ++i)
			visited[i] = false;
		
		System.out.print(sx + 1 + " ");
		visited[sx] = true;
		
		for(int i = 0; i < dim; ++i){
			if(!visited[i] && graph[sx][i] == 1){
				DFSnode(graph, i, visited);
			}
		}
	}
	
	public static void DFSnode(int [][] graph, int node, boolean [] visited){
		int dim = graph.length;
		System.out.print(node + 1 + " ");
		visited[node] = true;
		
		for(int i = 0; i < dim; ++i){
			if(!visited[i] && graph[node][i] == 1){
				DFSnode(graph, i, visited);
			}
		}
	}


测试数据同BSF,测试以1为起点的遍历结果:1 2 3 5 4 7 6 8 

迪杰斯特拉算法

痛心疾首,华为FX计划有一道编程题考点就是dijstra思想,但是忘记了,着重复习一下:


1首先取一个起点,设置一个数组dist,记录起点到各个节点的距离,无法到达的设置为maxint。

2然后选一个dist里面的最小值,把这个节点标记为已选(加入已选节点集合),然后重新计算dist:

3如果其他节点的dist能因为加入此次的已选节点变小,则更新dist(以此次已选节点为辅助节点,曲线救国)

4再次从dist数组里挑选最小值,回到第二步。


public static void dijstra(int [][] gweight, int start, int end){
		int dim = gweight.length;
		
		int [] father = new int [dim];
		int [] dist = new int [dim];
		HashSet<Integer> hash = new HashSet<Integer>();
		
		int maxint = Integer.MAX_VALUE;
		
		for(int i = 0; i < dim; ++i)
			dist[i] = maxint;
		
		int pickVer = start;
		int min = 0;
		hash.add(pickVer);
		
		while(pickVer != end){
			
			for(int i = 0; i < dim; ++i){
				if(gweight[pickVer][i] + min < dist[i] &&
						gweight[pickVer][i] != 0 &&
						!hash.contains(i)){
					
					dist[i] = gweight[pickVer][i] + min;
					father[i] = pickVer;
				}
			}
			
			int temp = maxint; int minindex = 0;
			for(int i = 0; i < dim; ++i){
				if(dist[i] < temp && !hash.contains(i)){
					temp = dist[i];
					minindex = i;
				}
			}
			
			min = temp;
			pickVer = minindex;
			hash.add(pickVer);
		}
		
		System.out.println("由节点 " + (start + 1) + " 至节点 " + (end + 1) + " 的最短路径长:"+dist[end]);
		
		System.out.print("节点路径为:" + (end + 1));
		for(int i = end; i != start;){
			System.out.print("<-" + (father[i] + 1));
			i = father[i];
		}
	}


测试数据:

int [][] weight ={{0,3,0,0,0,0,0,0},
						{3,0,4,7,0,0,0,0},
						{0,4,0,0,6,1,0,0},
						{0,7,0,0,1,0,5,0},
						{0,0,6,1,0,0,0,2},
						{0,0,1,0,0,0,8,0},
						{0,0,0,5,0,8,0,0},
						{0,0,0,0,2,0,0,0}};

结果:由节点 1 至节点 7 的最短路径长:15
   节点路径为:7<-4<-2<-1

代码中father数组记录了每个节点的上一个节点,用来记录最短路经过的节点路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值