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. 微信js-sdk注意事项

    1.录音结束后播放需要localId,用 var voice = { localId: '', serverId: '' }; 来存储,然后用voice.localId引用 2.token和ticke ...

  2. Jexus-5.6.3使用详解、Jexus Web Server配置

    一.Jexus Web Server配置   在 jexus 的工作文件夹中(一般是“/usr/jexus”)有一个基本的配置文件,文件名是“jws.conf”. jws.conf 中至少有 Site ...

  3. 基于Python实现对PDF文件的OCR识别

    http://www.jb51.net/article/89955.htm https://pythontips.com/2016/02/25/ocr-on-pdf-files-using-pytho ...

  4. angularJS学习之旅(1)

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  5. 浏览器User-agent String里的历史故事

    你是否好奇标识浏览器身份的User-Agent,为什么每个浏览器都有Mozilla字样? Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ...

  6. 第一个sprint与第二个sprint 阶段总结

    总体来说: 1.团队合作情况: 整个队伍配合得还算是不错的了,有些队员比较积极与主动,这是比较好的现象,因为一个队伍最终要的是活力与团结,至少我是这样认为的,如果一个队伍每个人都不干活,我想后果是不堪 ...

  7. java编程之:org.apache.commons.lang3.text.StrTokenizer

    第一个api测试:按特殊符号进行分词,并遍历每一个分词部分 public static void main(String[] args) { String aString="AB-CD-EF ...

  8. git 入门与应用

    git可视化界面的项目版本控制软件,适用于git项目管理 SourceTree 安装方法 https://blog.csdn.net/qq_26230421/article/details/79921 ...

  9. 【第一部分】04Leetcode刷题

    一.反转链表 II /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; ...

  10. Linux下修改MySQL数据库字符编码为UTF-8解决中文乱码

    由于MySQL编码原因会导致数据库出现乱码. 解决办法: 修改MySQL数据库字符编码为UTF-8,UTF-8包含全世界所有国家需要用到的字符,是国际编码. 具体操作: 1.进入MySQL控制台 &g ...