算法系列(十三)图论基本概念和拓扑排序

来源:互联网 发布:linux 进程启动时间 编辑:程序博客网 时间:2024/06/06 02:00

图的定义

一个图G=(V,E),由定点的集合V,和边的集合E组成。每一条边都是一副点对(v,w),边也称作弧,边上可以有权值。如果点对是有序的,那么图就是有向的。

图中的一条路径是一个顶点序列w1,w2,w3......wN,如果图中包含一条从顶点到自身的边,那么这个路径就是环。

有向无环图也成为DAG

如果在一个无向图中每个顶点到其它顶点都存在路径,则称这个无向图是连通的。具有这样性质的有向图被称为是强连通的。如果一个有向图不是强连通的,但是去掉方向后的基础图是连通的,那么该有向图称为是弱连通的。完全图是每一对顶点间都存在一条边的图。

进入一个顶点的边的个数称为该顶点的入度。每个有向无环图必定至少存在一个入度为0的顶点,至少存在一个出度为0的顶点,否则图中必然存在环。

图的表示

表示图的一种简单方法是使用一个二维数组,称为邻接矩阵。

如果图是稀疏的,更好的解决方法是使用邻接表。



拓扑排序

拓扑排序是对有向五环图的顶点排序,使得如果存在一条vi到vj的路径,那么在排序中vj在vi的后面。拓扑排序是不唯一的。

该DAG的拓扑序列为A B C D或者A C B D

拓扑排序的实现

先找出任意一个没有入边的顶点,然后显示该顶点,将它及其边删除,然后对图的其余部分做相同处理。

package com.algorithm.graphics;import java.util.Stack;import java.util.Vector;/** * 拓扑排序 *  * @author chao * */public class TopSortGraph {int vertexNum;Vector[] vector;Stack stack;int[] result;int[] in;// 入度/** *  * 构造一个图 *  * @param num *            图的顶点数 *  */public TopSortGraph(int num) {vertexNum = num;vector = new Vector[vertexNum];stack = new Stack();result = new int[vertexNum];in = new int[vertexNum];}/** * 向图中添加无向边 *  * @param I *            边的一个顶点 * @param J *            边的另一个顶点 * @return 是否添加成功 */public boolean addEdge(int I, int J) {/** * 判断用户输入的是否是一个顶点,如果是,则返回flase,添加不成功 */if (J == I) {return false;}/** * 判断所输入的顶点值是否在图所顶点范围值内,如果不在,则提示顶点不存在 *  */if (I < vertexNum && J < vertexNum && I >= 0 && J >= 0) {/** *  * 判断边是否存在 */if (isEdgeExists(I, J)) {return false;}/** * 添加边,将孤头的入度加1 */vector[I].add(J);in[J]++;return true;}return false;}/** * 判断有向边是否存在 *  * @param i *            要查询的有向边的一个孤尾 * @param j *            要查询的有向边的另一个孤头 * @return 边是否存在,false:不存在,true:存在 */public boolean isEdgeExists(int i, int j) {/** * 判断所输入的顶点值是否在图所顶点范围值内,如果不在,则提示顶点不存在 *  */if (i < vertexNum && j < vertexNum && i >= 0 && j >= 0) {if (i == j) {return false;}/** * 判断i的邻接结点集是否为空 */if (vector[i] == null) {vector[i] = new Vector();}/** * 判断这条边是否存在,如果存在,则提示边已经存在 */for (int q = 0; q < vector[i].size(); q++) {if (((Integer) vector[i].get(q)).intValue() == j) {System.out.println("顶点" + i + "和" + "顶点" + j + "这两点之间存在边");return true;}}}return false;}/** * 拓扑排序 */public void TopSort() {for (int i = 0; i < vertexNum; i++)if (in[i] == 0)stack.push(i);int k = 0;while (!stack.isEmpty()) {result[k] = (Integer) stack.pop();if (vector[result[k]] != null) {for (int j = 0; j < vector[result[k]].size(); j++) {int temp = (Integer) vector[result[k]].get(j);if (--in[temp] == 0) {stack.push(temp);}}}k++;}if (k < vertexNum) {System.out.println("有回路");System.exit(0);}}/** * 拓扑结果 *  * @return */public int[] getResult() {return result;}}


代码实现可以看github,地址https://github.com/robertjc/simplealgorithm
github代码也在不断完善中,有些地方可能有问题,还请多指教

欢迎扫描二维码,关注公众号


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 魔域快捷键锁了怎么办 宝宝走路o型腿怎么办 走路多了腿疼怎么办 孩子与父母相冲怎么办 压片机冲模锈了怎么办 宝宝腹泻10多天怎么办 10个月宝宝腹泻怎么办 5岁宝宝很叛逆怎么办 6岁了不会写字怎么办 宝宝1岁不爱吃饭怎么办 l岁宝宝不吃饭怎么办 1岁宝宝不肯吃饭怎么办 10岁儿童不吃饭怎么办 2周岁宝宝不吃饭怎么办 9个月小孩不吃饭怎么办 孩子被老师打了怎么办 孩子说老师打她怎么办 孩子的数学太差怎么办 2岁宝宝老要喝水怎么办 分手了还想她怎么办 5岁宝宝不会说话怎么办 2岁半宝宝说话晚怎么办 7岁儿童发烧39度怎么办 感冒发烧怎么办简单的退烧方法 生完孩子没奶水怎么办 梦见让狐狸咬了怎么办 1岁宝宝不吃辅食怎么办 母乳不够宝宝不吃奶粉怎么办 吃母乳的宝宝不吃奶粉怎么办 宝宝吃母乳不吃奶粉怎么办 1岁婴儿不吃辅食怎么办 不喝奶瓶的宝宝怎么办 母乳不足宝宝不吃奶粉怎么办 4岁宝宝注意力不集中怎么办 孩子上课不专心听讲怎么办 小孩上课不认真听讲怎么办 一年级孩子上课不认真听讲怎么办 打了孩子很自责怎么办 4岁宝宝讲话结巴怎么办 网销客户不说话怎么办 两岁宝宝不说话怎么办?