StackX.java
package demo;
public class StackX {
private final int SIZE = 20;
private int[] st;
private int top;
public StackX(){
st = new int[SIZE];
top = -1;
}
public void push(int j){
st[++top] = j;
}
public int pop(){
return st[top--];
}
public int peek(){
return st[top];
}
public boolean isEmpty(){
return (top==-1);
}
}
QueueX.java
package demo;
public class QueueX {
private final int SIZE = 20;
private int[] queArray;
private int front;
private int rear;
public QueueX(){
queArray = new int[SIZE];
front = 0;
rear = -1;
}
public void insert(int j){
if (rear == SIZE-1)
rear = -1;
queArray[++rear] = j;
}
public int remove(){
int temp = queArray[front++];
if (front == SIZE){
front = 0;
}
return temp;
}
public boolean isEmpty(){
return (rear+1 == front || front+SIZE-1 == rear);
}
}
DirectedGraph.java
package demo;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
public class DirectedGraph {
private class Vertex{
private String vertexLabel;// 顶点标识
private List<Edge> adjEdges;
private int inDegree;// 该顶点的入度
public Vertex(String verTtexLabel) {
this.vertexLabel = verTtexLabel;
inDegree = 0;
adjEdges = new LinkedList<Edge>();
}
}
private class Edge {
private Vertex endVertex;
// private double weight;
public Edge(Vertex endVertex) {
this.endVertex = endVertex;
}
}
private Map<String, Vertex> directedGraph;
public DirectedGraph(String[] graphContent) {
directedGraph = new LinkedHashMap<String, DirectedGraph.Vertex>();
buildGraph(graphContent);
}
private void buildGraph(String[] lines) {
Vertex startNode, endNode;
String startNodeLabel, endNodeLabel;
Edge e;
for (int i = 0; i < lines.length; i++) {
String[] nodesInfo = lines[i].split(",");
startNodeLabel = nodesInfo[0];
endNodeLabel = nodesInfo[1];
startNode = directedGraph.get(startNodeLabel);
if(startNode == null){
startNode = new Vertex(startNodeLabel);
directedGraph.put(startNodeLabel, startNode);
}
endNode = directedGraph.get(endNodeLabel);
if(endNode == null){
endNode = new Vertex(endNodeLabel);
directedGraph.put(endNodeLabel, endNode);
}
e = new Edge(endNode);//每读入一行代表一条边
startNode.adjEdges.add(e);//每读入一行数据,起始顶点添加一条边
endNode.inDegree++;//每读入一行数据,终止顶点入度加1
}
}
public void topoSort() throws Exception{
int count = 0;
Queue<Vertex> queue = new LinkedList<>();// 拓扑排序中用到的栈,也可用队列.
//扫描所有的顶点,将入度为0的顶点入队列
Collection<Vertex> vertexs = directedGraph.values();
for (Vertex vertex : vertexs)
if(vertex.inDegree == 0)
queue.offer(vertex);
while(!queue.isEmpty()){
Vertex v = queue.poll();
System.out.print(v.vertexLabel + " ");
count++;
for (Edge e : v.adjEdges)
if(--e.endVertex.inDegree == 0)
queue.offer(e.endVertex);
}
if(count != directedGraph.size())
throw new Exception("Graph has circle");
}
}
main
package demo;
public class Gra {
private final int MAX_VERTS = 20;//表示顶点的个数
private Vertex vertexList[];//用来存储顶点的数组
private int adjMat[][];//用邻接矩阵来存储边,数组元素表示没有边界,1表示有边界
private int nVerts;//顶点个数
private StackX theStack;//用栈实现深度优先搜索
private QueueX queue;//用队列实现广度优先搜索
/**
* 顶点类
* */
class Vertex{
public char label;
public boolean wasVisited;
public Vertex(char label){
this.label = label;
wasVisited = false;
}
}
public Gra(){
vertexList = new Vertex[MAX_VERTS];
adjMat = new int[MAX_VERTS][MAX_VERTS];
nVerts = 0;//初始化顶点个数为0
//初始化邻接矩阵所有元素都为0,即所有顶点都没有边
for (int i=0;i<MAX_VERTS;i++){
for (int j=0;j<MAX_VERTS;j++){
adjMat[i][j] = 0;
}
}
theStack = new StackX();
queue = new QueueX();
}
//将顶点添加到数组中,是否访问标志置为wasVisited=false(未访问)、
public void addVertex(char lab){
vertexList[nVerts++] = new Vertex(lab);
}
//注意用邻接矩阵表示边,是对称的,两部分都要赋值
public void addEdge(int start,int end,int weight){
int idx1 = start - 65;
int idx2 = end - 65;
adjMat[idx1][idx2] = 1;
adjMat[idx2][idx1] = 1;
}
//打印某个顶点表示的值
public void displayVertex(int v){
System.out.print(vertexList[v].label+" ");
}
/**深度优先搜索算法
* 1、用peek方法检查栈顶的顶点
* 2、用getAdjUnvisitedVertex方法找到当前栈顶邻接且未被访问的顶点
* 3、第二步返回值不等于-1则找到下一个未访问的邻接顶点,访问这个顶点,并入栈
* 如第二步返回值等于-1,则没有找到,出栈
* */
public void depthFirstSearch(){
//从第一个顶点开始访问
vertexList[0].wasVisited = true;//访问之后标记为true
displayVertex(0);
theStack.push(0);
while (!theStack.isEmpty()){
//找到栈当前顶点邻接且未被访问的顶点
int v = getAdjUnvisitedVertex(theStack.peek());
if (v==-1){//如果当前顶点值为-1,则表示没有邻接且未被访问的顶点,那么出栈顶点
theStack.pop();
}else {
//否则访问下一个邻接点
vertexList[v].wasVisited = true;
displayVertex(v);
theStack.push(v);
}
}
//栈访问完毕,重置所有标记位为false
for (int i=0;i<nVerts;i++){
vertexList[i].wasVisited = false;
}
}
//找到与某一顶点邻接且未被访问的顶点
public int getAdjUnvisitedVertex(int v){
for (int i=0;i<nVerts;i++){
//v顶点与i顶点相邻且未被访问
if (adjMat[v][i]==1&&vertexList[i].wasVisited==false)
return i;
}
return -1;
}
/**广度优先搜索
* 1、用remove方法检查栈顶的栈顶
* 2、试图找到这个顶点还未被访问的邻接点
* 3、如果没有找到,该顶点出列
* 4、如果找到这样的顶点,访问这个顶点,并把它放入队列中
* */
public void breadthFirstSearch(){
vertexList[0].wasVisited = true;
displayVertex(0);
queue.insert(0);
int v2;
while(!queue.isEmpty()){
int v1 = queue.remove();
while ((v2 =getAdjUnvisitedVertex(v1))!=-1){
vertexList[v2].wasVisited = true;
displayVertex(v2);
queue.insert(v2);
}
}
//搜索完毕,初始化,便于下次搜索
for (int i=0;i<nVerts;i++){
vertexList[i].wasVisited = false;
}
}
public static void main(String[] args) {
Gra graph = new Gra();
for (int i = 0; i < 10; i++) {
graph.addVertex((char)(65 + i));
}
graph.addEdge('A', 'B', 6);
graph.addEdge('B', 'C', 3);
graph.addEdge('A', 'I', 9);
graph.addEdge('A', 'D', 4);
graph.addEdge('D', 'B', 3);
graph.addEdge('B', 'E', 1);
graph.addEdge('D', 'E', 4);
graph.addEdge('E', 'C', 2);
graph.addEdge('C', 'F', 2);
graph.addEdge('E', 'F', 8);
graph.addEdge('D', 'G', 6);
graph.addEdge('G', 'E', 6);
graph.addEdge('E', 'H', 7);
graph.addEdge('H', 'F', 11);
graph.addEdge('I', 'G', 2);
graph.addEdge('G', 'J', 2);
graph.addEdge('I', 'J', 1);
graph.addEdge('G', 'H', 3);
graph.addEdge('J', 'H', 4);
System.out.println("深度优先搜索算法:");
graph.depthFirstSearch();
System.out.println();
System.out.println("---------------");
System.out.println("广度优先搜索算法:");
graph.breadthFirstSearch();
System.out.println("\n===============");
Gra graph2 = new Gra();
for (int i = 0; i < 16; i++) {
graph2.addVertex((char)(65 + i));
}
graph2.addEdge('A', 'B', 1);
graph2.addEdge('B', 'C', 18);
graph2.addEdge('C', 'D', 20);
graph2.addEdge('A', 'E', 2);
graph2.addEdge('E', 'F', 10);
graph2.addEdge('B', 'F', 4);
graph2.addEdge('F', 'G', 13);
graph2.addEdge('C', 'G', 1);
graph2.addEdge('G', 'H', 22);
graph2.addEdge('D', 'H', 4);
graph2.addEdge('E', 'I', 5);
graph2.addEdge('I', 'J', 11);
graph2.addEdge('J', 'F', 6);
graph2.addEdge('J', 'K', 4);
graph2.addEdge('K', 'G', 11);
graph2.addEdge('K', 'L', 23);
graph2.addEdge('H', 'L', 5);
graph2.addEdge('I', 'M', 3);
graph2.addEdge('M', 'N', 1);
graph2.addEdge('J', 'N', 9);
graph2.addEdge('N', 'O', 9);
graph2.addEdge('O', 'K', 12);
graph2.addEdge('O', 'P', 8);
graph2.addEdge('P', 'L', 9);
System.out.println("深度优先搜索算法:");
graph2.depthFirstSearch();
System.out.println();
System.out.println("---------------");
System.out.println("广度优先搜索算法:");
graph2.breadthFirstSearch();
System.out.println("\n===============");
String[] graphContent = "A,B;B,C;C,F;A,D;B,D;B,E;E,C;E,F;D,E;D,G;E,G;G,F;F,H;H,G;G,I;I,J;H,J".split(";");
DirectedGraph directedGraph = new DirectedGraph(graphContent);
try{
directedGraph.topoSort();
}catch(Exception e){
System.out.println("graph has circle");
//e.printStackTrace();
}
/*
* 输出
深度优先搜索算法:
A B C E D G H F J I
---------------
广度优先搜索算法:
A B D I C E G J F H
===============
深度优先搜索算法:
A B C D H G F E I J K L P O N M
---------------
广度优先搜索算法:
A B E C F I D G J M H K N L O P
===============
A B D E C graph has circle
*/
}
}