package graph;

import java.util.LinkedList;
import java.util.Queue;

import thinkinjava.net.mindview.util.Stack;

//类名:Vertex
//属性:
//方法:
class Vertex{
	public char label;	//点的名称,如A
	public boolean wasVisited;

	public Vertex(char lab){	//构造函数
		label = lab;
		wasVisited = false;
	}
}

//类名:Graph
//属性:
//方法:
class Graph{
	private final int MAX_VERTS = 20;
	private Vertex vertexList[];	//顶点列表数组
	private int adjMat[][];			//邻接矩阵
	private int nVerts;					//当前的顶点
	private char sortedArray[];

	public Graph(){	//构造函数
		vertexList = new Vertex[MAX_VERTS];
		adjMat = new int[MAX_VERTS][MAX_VERTS];
		nVerts = 0;
		for(int j=0;j<MAX_VERTS;j++){
			for(int k=0;k<MAX_VERTS;k++)
				adjMat[j][k] = 0;
		}
		sortedArray = new char[MAX_VERTS];
	}

	public void addVertex(char lab){	//添加新的顶点,传入顶点的lab,并修改nVerts
		vertexList[nVerts++] = new Vertex(lab);
	}

	public void addEdge(int start,int end){	//添加边,这里是无向图
		adjMat[start][end] = 1;
		//adjMat[end][start] = 1;
	}

	public void displayVertex(int v){	//显示顶点
		System.out.print(vertexList[v].label);
	}

	public int getAdjUnvisitedVertex(int v){	//返回一个和v邻接的未访问顶点
		for(int j=0;j<nVerts;j++)
			if(adjMat[v][j] == 1 && vertexList[j].wasVisited == false){
				return j;
			}
			return -1;	//如果没有,返回-1
	}

	public void dfs(){	//深度搜索
		Stack<Integer> theStack = new Stack<Integer>();
		vertexList[0].wasVisited = true;
		displayVertex(0);
		theStack.push(0);	//把根入栈

		while(!theStack.empty()){
			int v = getAdjUnvisitedVertex(theStack.peek());//取得一个和栈顶元素邻接的未访问元素
			if(v == -1)		//如果没有和栈顶元素邻接的元素,就弹出这个栈顶
				theStack.pop();
			else{				//如果有这个元素,则输出这个元素,标记为已访问,并入栈
				vertexList[v].wasVisited = true;
				displayVertex(v);
				theStack.push(v);
			}
		}
		for(int j=0;j<nVerts;j++)		//全部置为未访问
			vertexList[j].wasVisited = false;
	}

	public void bfs(){	//广度搜索
		Queue<Integer> theQueue = new LinkedList<Integer>();
		vertexList[0].wasVisited = true;
		displayVertex(0);
		theQueue.offer(0);	//把根入队列
		int v2;

		while(!theQueue.isEmpty()){
			int v1 = theQueue.remove();//v1记录第1层的元素,然后记录第2层第1个元素...

			while((v2=getAdjUnvisitedVertex(v1)) != -1){//输出所有和第1层邻接的元素,输出和第2层第1个元素邻接的元素...
				vertexList[v2].wasVisited = true;
				displayVertex(v2);
				theQueue.offer(v2);
			}
		}

		for(int j=0;j<nVerts;j++)		//全部置为未访问
			vertexList[j].wasVisited = false;
	}

	public void mst(){	//基于深度搜索的最小生成树
		Stack<Integer> theStack = new Stack<Integer>();
		vertexList[0].wasVisited = true;
		theStack.push(0);	//把根入栈

		while(!theStack.empty()){
			int currentVertex = theStack.peek();	//记录栈顶元素,当有为邻接元素的时候,才会输出
			int v = getAdjUnvisitedVertex(theStack.peek());//取得一个和栈顶元素邻接的未访问元素
			if(v == -1)		//如果没有和栈顶元素邻接的元素,就弹出这个栈顶
				theStack.pop();
			else{				//如果有这个元素,则输出这个元素,标记为已访问,并入栈
				vertexList[v].wasVisited = true;
				theStack.push(v);

				displayVertex(currentVertex);
				displayVertex(v);
				System.out.println();
			}
		}
		for(int j=0;j<nVerts;j++)		//全部置为未访问
			vertexList[j].wasVisited = false;
	}

	public int noSuccessors(){	//使用邻接矩阵找到没有后继的顶点,有后继顶点返回行数,没有返回-1
		boolean isEdge;

		for(int row=0;row<nVerts;row++){//从第1行开始
			isEdge = false;
			for(int col=0;col<nVerts;col++){//如果某一行某一列为1,返回这个行的行数
				if(adjMat[row][col] > 0){
					isEdge = true;
					break;
				}
			}
			if(!isEdge)
				return row;
		}
		return -1;
	}

	public void moveRowUp(int row,int length){
		for(int col=0;col<length;col++)
			adjMat[row][col] = adjMat[row+1][col];
	}

	public void moveColLeft(int col,int length){
		for(int row=0;row<length;row++)
			adjMat[row][col] = adjMat[row][col+1];
	}

	public void deleteVertex(int delVert){
		if(delVert != nVerts-1){
			for(int j=delVert;j<nVerts-1;j++)//在数组中去掉这个顶点
				vertexList[j] = vertexList[j+1];
			for(int row=delVert;row<nVerts-1;row++)//在邻接矩阵中把删除的这一行下的所有行上移
				moveRowUp(row,nVerts);
			for(int col=delVert;col<nVerts-1;col++)//在邻接矩阵中把删除的这一列下的所有列左移
				moveColLeft(col,nVerts-1);
		}
		nVerts--;
	}

	public void topo(){	//拓扑排序,必须在无环的有向图中进行,必须在有向图中
		int orig_nVerts = nVerts;	//记录有多少个顶点

		while(nVerts > 0){
			int currentVertex = noSuccessors();
			if(currentVertex == -1){
				System.out.println("错误:图含有环!");
				return;
			}
			sortedArray[nVerts-1] = vertexList[currentVertex].label;
			deleteVertex(currentVertex);
		}
		System.out.println("拓扑排序结果:");
		for(int j=0;j<orig_nVerts;j++)
			System.out.println(sortedArray[j]);

	}

}

public class graph_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Graph theGraph = new Graph();
		theGraph.addVertex('A');	//数组元素0
		theGraph.addVertex('B');	//数组元素1
		theGraph.addVertex('C');	//数组元素2
		theGraph.addVertex('D');	//数组元素3
		theGraph.addVertex('E');	//数组元素4

//		theGraph.addEdge(0, 1);	//AB
//		theGraph.addEdge(1, 2);	//BC
//		theGraph.addEdge(0, 3);	//AD
//		theGraph.addEdge(3, 4);	//DE

//		System.out.println("dfs访问的顺序:");
//		theGraph.dfs();
//		System.out.println();
//
//		System.out.println("bfs访问的顺序:");
//		theGraph.bfs();

//		theGraph.addEdge(0, 1);	//AB
//		theGraph.addEdge(0, 2);	//AC
//		theGraph.addEdge(0, 3);	//AD
//		theGraph.addEdge(0, 4);	//AE
//		theGraph.addEdge(1, 2);	//BC
//		theGraph.addEdge(1, 3);	//BD
//		theGraph.addEdge(1, 4);	//BE
//		//theGraph.addEdge(2, 3);	//CD
//		//theGraph.addEdge(2, 4);	//CE
//		theGraph.addEdge(3, 4);	//DE

//		System.out.println("最小生成树:");
//		theGraph.mst();

		theGraph.addVertex('F');	//数组元素5
		theGraph.addVertex('G');	//数组元素6
		theGraph.addVertex('H');	//数组元素6

		theGraph.addEdge(0, 3);	//AD
		theGraph.addEdge(0, 4);	//AE
		theGraph.addEdge(1, 4);	//BE
		theGraph.addEdge(2, 5);	//CF
		theGraph.addEdge(3, 6);	//DG
		theGraph.addEdge(4, 6);	//EG
		theGraph.addEdge(5, 7);	//FH
		theGraph.addEdge(6, 7);	//GH

		theGraph.topo();
	}

}

Java排序算法——拓扑排序的更多相关文章

  1. AOV网络和Kahn算法拓扑排序

    1.AOV与DAG 活动网络可以用来描述生产计划.施工过程.生产流程.程序流程等工程中各子工程的安排问题.   一般一个工程可以分成若干个子工程,这些子工程称为活动(Activity).完成了这些活动 ...

  2. 经典排序算法 - 高速排序Quick sort

    经典排序算法 - 高速排序Quick sort 原理,通过一趟扫描将要排序的数据切割成独立的两部分,当中一部分的全部数据都比另外一部分的全部数据都要小,然后再按此方法对这两部分数据分别进行高速排序,整 ...

  3. Java排序算法——桶排序

    文字部分为转载:http://hxraid.iteye.com/blog/647759 对N个关键字进行桶排序的时间复杂度分为两个部分: (1) 循环计算每个关键字的桶映射函数,这个时间复杂度是O(N ...

  4. 线性时间的排序算法--桶排序(以leetcode164. Maximum Gap为例讲解)

    前言 在比较排序的算法中,快速排序的性能最佳,时间复杂度是O(N*logN).因此,在使用比较排序时,时间复杂度的下限就是O(N*logN).而桶排序的时间复杂度是O(N+C),因为它的实现并不是基于 ...

  5. 排序算法——选择排序(js语言实现)

    选择排序:顾名思义选择,选择排序属于O(N^2)的排序算法,意思就是选择数组中的最小的拿出来放在第一位,然后再剩下的数里面,选择最小的,排在第二位,以此类推. 例如:8  3  4  5  6  2  ...

  6. 基本排序算法——shell排序java实现

    shell排序是对插入排序的一种改进. package basic.sort; import java.util.Arrays; import java.util.Random; public cla ...

  7. 基本排序算法——选择排序java实现

    选择排序与冒泡排序有很大的相同点,都是一次遍历结束后能确定一个元素的最终位置,其主要思路是,一次遍历选取最小的元素与第一个元素交换,从而使得一个个元素有序,而后选择第二小的元素与第二个元素交换,知道, ...

  8. Java排序算法——希尔排序

    package sort; //================================================= // File Name : ShellSort //------- ...

  9. Java排序算法——选择排序

    import java.util.Arrays; //================================================= // File Name : Select_S ...

随机推荐

  1. .Net语言 APP开发平台——Smobiler学习日志:如何在手机上实现电子签名功能

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的“Smobil ...

  2. java 线程协作 wait(等待)与 notiy(通知)

    一.wait().notify()和notifyAll() 为了更好的支持多线程之间的协作,JDK提供了三个重要的本地方法 //调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对 ...

  3. Hadoop阅读笔记(七)——代理模式

    关于Hadoop已经小记了六篇,<Hadoop实战>也已经翻完7章.仔细想想,这么好的一个框架,不能只是流于应用层面,跑跑数据排序.单表链接等,想得其精髓,还需深入内部. 按照<Ha ...

  4. 使用Masonry搭建特殊布局时与xib的对比

    之前只有比较浅的接触过Masonry.项目中大多数的布局还是用xib中的AutoLayout与手码的frame计算相结合,相信也会有很多项目和我一样是这两种布局的组合.其实xib各方面用的感觉都挺好, ...

  5. iOS证书失效

    iOS证书突然失效 今早上班打包直接报错,错误如图 根据错误信息到“钥匙串”里面看了一下证书,证书都莫名其妙的失效了,昨天还是好好的. 重新去钥匙串从证颁发中心获取证书,然后登陆开发者账号重新申请证书 ...

  6. iOS:图片拉伸不变形技巧

    方法: 假设图片为60*24 CGFloat top = image.height*0.5-1; // 顶端盖高度 CGFloat bottom = top ; // 底端盖高度 CGFloat le ...

  7. hdu 1829-A Bug&#39;s LIfe(简单带权并查集)

    题意:Bug有两种性别,异性之间才交往, 让你根据数据判断是否存在同性恋,输入有 t 组数据,每组数据给出bug数量n, 和关系数m, 以下m行给出相交往的一对Bug编号 a, b.只需要判断有没有, ...

  8. CentOS里下载百度网盘 / 360 网盘资源的方法

    wget -c --referer=引用地址 -O 文件名 "真实下载地址" 例如,我下载资源原在的页面为http://pan.baidu.com/s/1cfJXZ ,实际下载地址 ...

  9. APK签名校验绕过

    APK签名校验绕过 Android JNI 获取应用签名 android apk 防止反编译技术第一篇-加壳技术 android apk 防止反编译技术第五篇-完整性校验 利用IDA Pro反汇编程序 ...

  10. jQuery mobile 核心功能

    原文地址:http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/about/features.html 基于 jQuery 核心,使用和jQue ...