图的递归非递归深度优先搜索和广度优先搜索,两种最小生成树算法

代码如下:


以邻接矩阵构建图


public class Graph {

	public static void main(String[] args) {
		/**
		 * 定义一个图
		 * 
		 * 本次实验为无向图
		 * 
		 * 为了与平日思维习惯,第一行和第一列不用
		 * 
		 * 从map[1][1]算作第一个点
		 * 
		 * map:图
		 * 
		 * mapUsed:标识该结点有没有遍历到
		 * 
		 * edges:存储结点到结点的权重
		 */
		int[][] map = new int[10][10];
		boolean[] mapUsed = new boolean[10];
		Edge edges[] = new Edge[11];

		/**
		 * 初始化图
		 * 
		 */
		initMap(map, edges);

		/**
		 * 深度优先遍历
		 */
		Depth_First_Traversal(map, mapUsed);

		/**
		 * 广度优先遍历
		 */
		Breadth_First_Traversal(map, mapUsed);

		/**
		 * 两种方式求最小生成树
		 */
		Minimal_Spanning_Tree(map, edges);

	}

	/**
	 * 初始化图的数据
	 */
	public static void initMap(int[][] map, Edge[] edges) {

		/**
		 * 假定不能到达的点为Integer类型最大值
		 */
		for (int i = 0; i < 10; i++) {

			for (int j = 0; j < 10; j++) {

				map[i][j] = Integer.MAX_VALUE;

			}

		}

		/**
		 * 初始化图
		 */
		map[1][2] = 3;
		map[2][1] = 3;
		edges[1] = new Edge(1, 2, 3);

		map[2][8] = 10;
		map[8][2] = 10;
		edges[2] = new Edge(2, 8, 10);

		map[8][5] = 9;
		map[5][8] = 9;
		edges[3] = new Edge(5, 8, 9);

		map[7][9] = 4;
		map[9][7] = 4;
		edges[4] = new Edge(7, 9, 4);

		map[4][8] = 7;
		map[8][4] = 7;
		edges[5] = new Edge(4, 8, 7);

		map[3][7] = 18;
		map[7][3] = 18;
		edges[6] = new Edge(3, 7, 18);

		map[9][6] = 15;
		map[6][9] = 15;
		edges[7] = new Edge(6, 9, 15);

		map[4][5] = 13;
		map[5][4] = 13;
		edges[8] = new Edge(4, 5, 13);

		map[5][6] = 10;
		map[6][5] = 10;
		edges[9] = new Edge(5, 6, 10);

		map[4][7] = 23;
		map[7][4] = 23;
		edges[10] = new Edge(4, 7, 23);
	}

	/**
	 * 深度优先遍历
	 * 
	 * @param map
	 * @param mapUsed
	 */
	public static void Depth_First_Traversal(int[][] map, boolean[] mapUsed) {

		System.out.println("从点1,递归方式深度优先遍历图:");
		DFS_Recursion(map, mapUsed, 1);
		System.out.println();

		System.out.println("从点1,非递归方式深度优先遍历图:");
		DFS_NotRecursion(map);
		System.out.println();

	}

	/**
	 * 广度优先遍历
	 * 
	 * @param map
	 * @param mapUsed
	 */
	public static void Breadth_First_Traversal(int[][] map, boolean[] mapUsed) {

		System.out.println("从点1,非递归方式广度优先遍历图:");
		BFS_NotRecursion(map);
		System.out.println();

		mapUsed = new boolean[10];
		System.out.println("从点1,递归方式广度优先遍历图:");
		System.out.print(1 + " ");
		mapUsed[1] = true;
		Queue nextBFS = new Queue();
		BFS_Recursion(map, mapUsed, 1, nextBFS);
		System.out.println();

	}

	/**
	 * 求最小生成树
	 * 
	 * @param map
	 * @param edges
	 */
	public static void Minimal_Spanning_Tree(int[][] map, Edge[] edges) {

		System.out.println("Prim算法求最小生成树:");
		Prim(9, map);

		System.out.println("Kruskal算法求最小生成树:");
		Kruskal(edges);

	}

	/**
	 * 递归方式深度优先遍历
	 * 
	 * @param map
	 */
	public static void DFS_Recursion(int[][] map, boolean[] mapUsed, int next) {

		// 打印,即访问next结点
		System.out.print(next + " ");
		// 标识next结点已经被访问
		mapUsed[next] = true;

		// 在next结点的出度里寻找下一个
		for (int i = 1; i < map.length; i++) {

			// 找下一个需要遍历的点
			if (!mapUsed[i] && map[next][i] < 1000) {

				// 递归
				DFS_Recursion(map, mapUsed, i);

			}

		}
	}

	/**
	 * 递归方式广度优先遍历
	 * 
	 * @param map
	 */
	public static void BFS_Recursion(int[][] map, boolean[] mapUsed, int next,
			Queue nextBFS) {

		// 在next结点的出度里寻找下一个
		for (int i = 1; i < map.length; i++) {

			// 如果没有访问
			if (!mapUsed[i] && map[next][i] < 1000) {

				// 访问i结点
				mapUsed[i] = true;
				System.out.print(i + " ");

				// 将i结点排入队列
				nextBFS.enQueue(i);

			}

		}

		// 如果队列不为空
		while (!nextBFS.isEmpty()) {

			// 出队列
			int nextBFSNumber = nextBFS.deQueue();

			// 递归
			BFS_Recursion(map, mapUsed, nextBFSNumber, nextBFS);
		}

	}

	/**
	 * 非递归方式深度优先遍历
	 * 
	 * @param map
	 */
	public static void DFS_NotRecursion(int[][] map) {

		Stack stack = new Stack();
		boolean[] mapUsed = new boolean[10];

		// 将1压入栈
		stack.push(1);
		System.out.print(1 + " ");
		mapUsed[1] = true;

		while (!stack.isEmpty()) {

			// 取得栈顶元素
			int next = stack.getTop();

			for (int i = 1; i < map.length; i++) {

				if (!mapUsed[i] && map[next][i] < 1000) {

					// 访问i结点
					mapUsed[i] = true;
					stack.push(i);

					System.out.print(i + " ");

					// 访问完i之后,重新得到栈顶元素,即i元素
					next = stack.getTop();
					// 重新遍历
					i = 1;
				}

			}

			// 如果执行到这一步,说明该点没有什么好遍历的了,从栈顶弹出
			stack.pop();

		}

	}

	/**
	 * 非递归方式广度优先遍历
	 * 
	 * @param map
	 */
	public static void BFS_NotRecursion(int[][] map) {

		Queue queue = new Queue();
		boolean[] mapUsed = new boolean[10];

		for (int i = 1; i < map.length; i++) {

			if (!mapUsed[i]) {

				mapUsed[i] = true;
				System.out.print(i + " ");

				// 将i排入队列
				queue.enQueue(i);

				// 如果队列不空,就接着执行
				while (!queue.isEmpty()) {

					// 取得队列的第一个值
					int next = queue.deQueue();

					for (int j = 1; j < 10; j++) {

						if (!mapUsed[j] && map[next][j] < 1000) {

							// 访问j
							mapUsed[j] = true;
							System.out.print(j + " ");

							// 将j排入队列
							queue.enQueue(j);

						}

					}

				}

			}

		}

	}

	/**
	 * Prim算法求最小生成树
	 * 
	 * @param map
	 * @return
	 */
	public static void Prim(int n, int[][] map) {

		// 权重
		int[] lowcost = new int[n + 1];
		// 相邻结点
		int[] closest = new int[n + 1];
		boolean[] s = new boolean[n + 1];

		s[1] = true;

		for (int i = 2; i <= n; i++) {

			lowcost[i] = map[1][i];
			closest[i] = 1;

		}

		// 取得lowcost中最小值的点
		for (int i = 1; i < n; i++) {

			int min = Integer.MAX_VALUE;
			int j = 1;

			for (int k = 2; k <= n; k++) {
				if ((lowcost[k] < min) && (!s[k])) {

					min = lowcost[k];
					j = k;

				}
			}

			// 访问j结点
			System.out.println(j + ", " + closest[j]);
			s[j] = true;

			// 依次遍历k,找出j到k结点的最小值,给lowcost[k]
			// 距离k最近的结点为:closest[k]=j
			for (int k = 2; k <= n; k++) {
				if ((map[j][k] < lowcost[k]) && (!s[k])) {

					lowcost[k] = map[j][k];
					closest[k] = j;

				}
			}

		}

	}

	/**
	 * Kruskal算法求最小生成树
	 * 
	 * @param edges
	 * @return
	 */
	public static void Kruskal(Edge edges[]) {

		int[] parent = new int[100];

		// 冒泡排序,将edges数组中的Edge按weight升序排列
		for (int i = edges.length - 1; i > 0; i--) {

			for (int j = 1; j < i; j++) {

				if (edges[j].weight > edges[j + 1].weight) {

					int bTemp = edges[j].begin;
					int eTemp = edges[j].end;
					int wTemp = edges[j].weight;

					edges[j].begin = edges[j + 1].begin;
					edges[j].end = edges[j + 1].end;
					edges[j].weight = edges[j + 1].weight;

					edges[j + 1].begin = bTemp;
					edges[j + 1].end = eTemp;
					edges[j + 1].weight = wTemp;

				}

			}

		}

		for (int i = 1; i < edges.length; i++) {

			// 寻找指向i边头结点的结点
			int n = Find(parent, edges[i].begin);
			// 寻找指向i边尾结点的结点
			int m = Find(parent, edges[i].end);

			// 如果没有形成回路
			// 因为parent的值都在一条树枝上,即如果i.begin和i.end在一条树枝上,则n必定与m相等
			if (n != m) {

				// 指向n结点的是m结点
				parent[n] = m;
				System.out.println(edges[i].begin + " " + edges[i].end + " "
						+ edges[i].weight);

			}

		}

	}

	/**
	 * 寻找相连结点
	 * 
	 * @param parent
	 * @param f
	 * @return
	 */
	public static int Find(int[] parent, int f) {

		// 直到一条链最后的那个结点
		while (parent[f] > 0) {
			f = parent[f];
		}
		// 返回该结点
		return f;
	}

}

/**
 * 边
 * 
 * weight:权重
 * 
 * begin:起始结点
 * 
 * end:结束结点
 * 
 * @author wanfeng
 * 
 */
class Edge {

	public int weight;
	public int begin, end;

	Edge(int uu, int vv, int ww) {
		begin = uu;
		end = vv;
		weight = ww;
	}

}

/**
 * 数据结构:栈
 * 
 * 
 * @author wanfeng
 * 
 */
class Stack {

	private int[] element;
	private int length;

	public Stack() {

		element = new int[100];
		length = -1;

	}

	/**
	 * 将元素压入栈顶
	 * 
	 * @param integer
	 */
	public void push(int integer) {

		length++;
		element[length] = integer;

	}

	/**
	 * 得到栈顶元素
	 * 
	 * @return
	 */
	public int getTop() {

		return element[length];

	}

	/**
	 * 得到并删除栈顶元素
	 * 
	 * @return
	 */
	public int pop() {

		int res = element[length];

		length--;

		return res;
	}

	/**
	 * 因为初始值为-1,所以与-1进行判断
	 * 
	 * @return
	 */
	public boolean isEmpty() {

		return length == -1;

	}

}

/**
 * 数据结构:队列
 * 
 * @author wanfeng
 * 
 */
class Queue {

	private int[] element;
	private int length;

	public Queue() {
		element = new int[100];
		length = 0;
	}

	public void enQueue(int integer) {

		element[length] = integer;

		length++;

	}

	public int deQueue() {

		int res = element[0];

		for (int i = 0; i < length; i++) {

			element[i] = element[i + 1];

		}
		length--;

		return res;
	}

	public boolean isEmpty() {

		return length == 0;

	}

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值