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. [mark] 使用Sublime Text 2时如何将Tab配置为4个空格

    在Mac OS X系统下,Sublime Text是一款比较赞的编辑器. 作为空格党的自觉,今天mark一下使用Sublime Text 2时如何将Tab配置为4个空格: 方法来自以下两个链接: ht ...

  2. mysql使用load导入txt文件所遇到的问题及解决方法

    导入txt文件,有导入向导这种方式: 另外可以使用load的方式导入.最开始使用以下代码插入: load data local infile 'F:\\Data\\predict_data.txt' ...

  3. The transaction log for database &#39;tempdb&#39; is full due to &#39;ACTIVE_TRANSACTION&#39;

    今天早上,Dev跟我说,执行query statement时出现一个error,detail info是: “The transaction log for database 'tempdb' is ...

  4. Linux环境下vsftpd参数配置

    很久之前就用过vsftpd,但总是忘了参数该如何配置,今天特地有搜索了一遍,把配置方法整理如下: (1)检查是否已安装vsftpd #rpm -qa | grep vsftpd vsftpd--.el ...

  5. printf(&quot;%*s\n&quot;, 1, &quot;&quot;); 使用&quot;printf();&quot; 的格式化输出动态制定等宽度输出。

    #include <stdio.h> #include <string.h> int main() { const char the_text[] = "this i ...

  6. struts2与struts1整合,Unable to load configuration. - interceptor-ref ... struts.xml

    struts.xml中为了与struts1的MVC模式整合,需要类似如下的拦截器的引用 <interceptor-stack name="integration"> & ...

  7. ado执行sql查询出现“发送数据流时出现算术溢出”错误

    开发一个数据采集监控系统,比较变态的是有将近2000项数据.根据数据类型分多个表存储.数据库访问层采用ado.最近发现当一条sql一次性查询1700多个字段数据后就出现“发送数据流时出现算术溢出”错误 ...

  8. Oracle数据库管理之创建和删除数据库

    转自:http://supportopensource.iteye.com/blog/678898 一.数据库管理概述 在完成Oracle软件安装后,DBA就应该对组织和管理数据库负责任,其主要任务是 ...

  9. 2013 Multi-University Training Contest 5 k-th point

    刚开始我也不知道怎么做,后来慢慢就推出来了…… 对于样例 2 1 0,结果是2/3 2 2 0,结果是4/5 3 2 0,结果是6/7 3 2 1,结果是9/14=6/7*3/4 …… 之后就会发现每 ...

  10. SQL 各种连接:内连接,外连接(左外,右外,完全外)

    在讲述之前,假设有如下两个表EMP, DEPT, 并且他们数据如下: