// 實驗小結 吳新強於2013年3月19日18:45:59 桂電 2507實驗室
// 主要學習圖結構的實現輸出以及圖結構的深度和廣度優先搜索和Dijkstra 算法的最小路徑以及最小生成樹的實現
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Chapter16
{
class Program
{
static void Main(string[] args)
{
// 簡單的圖輸出
Console.WriteLine("簡單的圖輸出:");
Graph the1Graph = new Graph(4);
the1Graph.AddVertex("A");
the1Graph.AddVertex("B");
the1Graph.AddVertex("C");
the1Graph.AddVertex("D");
the1Graph.AddEdge(0, 1);
the1Graph.AddEdge(1, 2);
the1Graph.AddEdge(2, 3);
the1Graph.TopSort();
Console.WriteLine();
Console.WriteLine("完成.");
Console.WriteLine();
Graph theGraph = new Graph(6);
theGraph.AddVertex("CS1");
theGraph.AddVertex("CS2");
theGraph.AddVertex("DS");
theGraph.AddVertex("OS");
theGraph.AddVertex("ALG");
theGraph.AddVertex("AL");
theGraph.AddEdge(0, 1);
theGraph.AddEdge(1, 2);
theGraph.AddEdge(1, 5);
theGraph.AddEdge(2, 3);
theGraph.AddEdge(2, 4);
theGraph.TopSort();
Console.WriteLine();
Console.WriteLine("完成.");
// theGraph.ShowVertex(4);
Console.WriteLine("輸出沒有後繼結點頂點:" + theGraph.NoSuccessors());
theGraph.DelVertex(1);
// theGraph.TopSort();
Console.WriteLine();
//圖的深度優先搜索
Console.WriteLine("圖的深度優先搜索:");
Graph aGraph = new Graph(13);
aGraph.AddVertex("A");
aGraph.AddVertex("B");
aGraph.AddVertex("C");
aGraph.AddVertex("D");
aGraph.AddVertex("E");
aGraph.AddVertex("F");
aGraph.AddVertex("G");
aGraph.AddVertex("H");
aGraph.AddVertex("I");
aGraph.AddVertex("J");
aGraph.AddVertex("K");
aGraph.AddVertex("L");
aGraph.AddVertex("M");
aGraph.AddEdge(0, 1);
aGraph.AddEdge(1, 2);
aGraph.AddEdge(2, 3);
aGraph.AddEdge(0, 4);
aGraph.AddEdge(4, 5);
aGraph.AddEdge(5, 6);
aGraph.AddEdge(0, 7);
aGraph.AddEdge(7, 8);
aGraph.AddEdge(8, 9);
aGraph.AddEdge(0, 10);
aGraph.AddEdge(10, 11);
aGraph.AddEdge(11, 12);
Console.WriteLine();
aGraph.DepthFirstSearch();
Console.WriteLine();
//圖的深度優先搜索
Console.WriteLine("圖的廣度優先搜索:");
Graph bGraph = new Graph(13);
bGraph.AddVertex("A");
bGraph.AddVertex("B");
bGraph.AddVertex("C");
bGraph.AddVertex("D");
bGraph.AddVertex("E");
bGraph.AddVertex("F");
bGraph.AddVertex("G");
bGraph.AddVertex("H");
bGraph.AddVertex("I");
bGraph.AddVertex("J");
bGraph.AddVertex("K");
bGraph.AddVertex("L");
bGraph.AddVertex("M");
bGraph.AddEdge(0, 1);
bGraph.AddEdge(1, 2);
bGraph.AddEdge(2, 3);
bGraph.AddEdge(0, 4);
bGraph.AddEdge(4, 5);
bGraph.AddEdge(5, 6);
bGraph.AddEdge(0, 7);
bGraph.AddEdge(7, 8);
bGraph.AddEdge(8, 9);
bGraph.AddEdge(0, 10);
bGraph.AddEdge(10, 11);
bGraph.AddEdge(11, 12);
Console.WriteLine();
bGraph.BreadthFirstSearch();
Console.WriteLine();
// 最小生成樹
Console.WriteLine("最新生成樹:");
Console.WriteLine();
Graph cGraph = new Graph(7);
cGraph.AddVertex("A");
cGraph.AddVertex("B");
cGraph.AddVertex("C");
cGraph.AddVertex("D");
cGraph.AddVertex("E");
cGraph.AddVertex("F");
cGraph.AddVertex("G");
cGraph.AddEdge(0, 1);
cGraph.AddEdge(0, 2);
cGraph.AddEdge(0, 3);
cGraph.AddEdge(1, 2);
cGraph.AddEdge(1, 3);
cGraph.AddEdge(1, 4);
cGraph.AddEdge(2, 3);
cGraph.AddEdge(2, 5);
cGraph.AddEdge(3, 5);
cGraph.AddEdge(3, 4);
cGraph.AddEdge(3, 6);
cGraph.AddEdge(4, 5);
cGraph.AddEdge(4, 6);
cGraph.AddEdge(5, 6);
// Console.WriteLine();
cGraph.Mst();
Console.WriteLine();
/*
// Dijkstra 查找最短路徑
Graph dGraph = new Graph();
dGraph.AddVertex("A");
dGraph.AddVertex("B");
dGraph.AddVertex("C");
dGraph.AddVertex("D");
dGraph.AddVertex("E");
dGraph.AddVertex("F");
dGraph.AddVertex("G");
dGraph.AddEdge(0, 1, 2);
dGraph.AddEdge(0, 3, 1);
dGraph.AddEdge(1, 3, 3);
dGraph.AddEdge(1, 4, 10);
dGraph.AddEdge(2, 5, 5);
dGraph.AddEdge(2, 0, 4);
dGraph.AddEdge(3, 2, 2);
dGraph.AddEdge(3, 5, 8);
dGraph.AddEdge(3, 4, 2);
dGraph.AddEdge(3, 6, 4);
dGraph.AddEdge(4, 6, 6);
dGraph.AddEdge(6, 5, 1);
Console.WriteLine();
Console.WriteLine("最短路徑:");//Shortest paths
Console.WriteLine();
// dGraph.Path();
Console.WriteLine();
*/
}
}
public class Vertex
{
public bool wasVisited;
public bool isinTree;
public string label;
public Vertex(string label)
{
this.label = label;
// label = label;
wasVisited = false;
// isinTree = false;
}
}
public class Graph
{
private int NUM_VERTICES = 6;
private Vertex[] vertices;
private int[,] adjMatrix;
int numVerts;
/* private const int max_verts = 20;
// int infinity = 1000000;
// Vertex[] vertexList;
// int[,] adjMat;
// int nVerts;
// int nTree;
// DistOriginal[] sPath;
// int currentVert;
// int startToCurrent;
*/
/* public Graph()
{
vertexList = new Vertex[max_verts];
adjMat = new int[max_verts, max_verts];
nVerts = 0;
nTree = 0;
for (int j = 0; j <= max_verts - 1; j++)
for (int k = 0; k <= max_verts - 1; k++)
adjMat[j, k] = infinity;
// sPath = new DistOriginal[max_verts];
}
*/
public Graph(int numvertices)
{
NUM_VERTICES = numvertices;
vertices = new Vertex[NUM_VERTICES];
adjMatrix = new int[NUM_VERTICES, NUM_VERTICES];
numVerts = 0;
for (int j = 0; j <= NUM_VERTICES - 1; j++)
for (int k = 0; k <= NUM_VERTICES - 1; k++)
adjMatrix[j, k] = 0;
}
public void AddVertex(string label)
{
vertices[numVerts] = new Vertex(label);
numVerts++;
// vertexList[nVerts] = new Vertex(label);
// nVerts++;
}
public void AddEdge(int start, int eend)
{
adjMatrix[start, eend] = 1;
}
// public void AddEdge(int start, int theEnd, int weight)
// {
// adjMat[start, theEnd] = weight;
// }
public void ShowVertex(int v)
{
Console.Write(vertices[v].label + " ");
}
public int NoSuccessors()
{
bool isEdge;
for (int row = 0; row <= NUM_VERTICES - 1; row++)
{
isEdge = false;
for (int col = 0; col <= NUM_VERTICES - 1; col++)
{
if (adjMatrix[row, col] > 0)
{
isEdge = true;
break;
}
}
if (!isEdge)
return row;
}
return -1;
}
public void DelVertex(int vert)
{
if (vert != NUM_VERTICES - 1)
{
for (int j = vert; j < NUM_VERTICES - 1; j++)
vertices[j] = vertices[j + 1];
for (int row = vert; row < NUM_VERTICES - 1; row++)
MoveRow(row, NUM_VERTICES);
for (int col = vert; col < NUM_VERTICES - 1; col++)
MoveCol(col, NUM_VERTICES);
}
NUM_VERTICES--;
}
private void MoveRow(int row, int length)
{
for (int col = 0; col <= length - 1; col++)
adjMatrix[row, col] = adjMatrix[row + 1, col];
}
private void MoveCol(int col, int length)
{
for (int row = 0; row <= length - 1; row++)
adjMatrix[row, col] = adjMatrix[row, col + 1];
}
public void TopSort()
{
Stack<string> gStack = new Stack<string>();
while (NUM_VERTICES > 0)
{
int currVertex = NoSuccessors();
if (currVertex == -1)
{
Console.WriteLine("錯誤:圖中存在環路!");//Error: graph has cycles.
return;
}
gStack.Push(vertices[currVertex].label);
DelVertex(currVertex);
}
Console.Write("圖的順序: ");//Topological sorting order
while (gStack.Count > 0)
Console.Write(gStack.Pop() + " ");
}
private int GetAdjUnvisitedVertex(int v)
{
for (int j = 0; j <= NUM_VERTICES - 1; j++)
if ((adjMatrix[v, j] == 1) && (vertices[j].wasVisited == false))
return j;
return -1;
}
//圖的深度優先搜索
public void DepthFirstSearch()
{
Stack<int> gStack = new Stack<int>();
vertices[0].wasVisited = true;
ShowVertex(0);
gStack.Push(0);
int v;
while (gStack.Count > 0)
{
v = GetAdjUnvisitedVertex(gStack.Peek());
if (v == -1)
gStack.Pop();
else
{
vertices[v].wasVisited = true;
ShowVertex(v);
gStack.Push(v);
}
}
for (int j = 0; j <= NUM_VERTICES - 1; j++)
vertices[j].wasVisited = false;
}
//圖的廣度優先搜索
public void BreadthFirstSearch()
{
Queue<int> gQueue = new Queue<int>();
vertices[0].wasVisited = true;
ShowVertex(0);
gQueue.Enqueue(0);
int vert1, vert2;
while (gQueue.Count > 0)
{
vert1 = gQueue.Dequeue();
vert2 = GetAdjUnvisitedVertex(vert1);
while (vert2 != -1)
{
vertices[vert2].wasVisited = true;
ShowVertex(vert2);
gQueue.Enqueue(vert2);
vert2 = GetAdjUnvisitedVertex(vert1);
}
}
for (int i = 0; i <= NUM_VERTICES - 1; i++)
vertices[i].wasVisited = false;
}
// 最小生成樹
public void Mst()
{
Stack<int> gStack = new Stack<int>();
vertices[0].wasVisited = true;
gStack.Push(0);
int currVertex, ver;
while (gStack.Count > 0)
{
currVertex = gStack.Peek();
ver = GetAdjUnvisitedVertex(currVertex);
if (ver == -1)
gStack.Pop();
else
{
vertices[ver].wasVisited = true;
gStack.Push(ver);
ShowVertex(currVertex);
ShowVertex(ver);
Console.Write(" ");
}
}
for (int j = 0; j <= NUM_VERTICES - 1; j++)
vertices[j].wasVisited = false;
}
// Dijkstra 查找最短路徑
/* public void Path()
{
int startTree = 0;
// vertexList[startTree].isInTree = true;
nTree = 1;
for (int j = 0; j <= nVerts; j++)
{
int tempDist = adjMat[startTree, j];
sPath[j] = new DistOriginal(startTree, tempDist);
}
while (nTree < nVerts)
{
int indexMin = GetMin();
int minDist = sPath[indexMin].distance;
currentVert = indexMin;
startToCurrent = sPath[indexMin].distance;
// vertexList[currentVert].isInTree = true;
nTree++;
AdjustShortPath();
}
DisplayPaths();
nTree = 0;
// for (int j = 0; j <= nVerts - 1; j++)
// vertexList[j].isInTree = false;
}
public int GetMin()
{
int minDist = infinity;
int indexMin = 0;
for (int j = 1; j <= nVerts - 1; j++)
// if (!(vertexList[j].isInTree) && sPath[j].distance < minDist)
{
minDist = sPath[j].distance;
indexMin = j;
}
return indexMin;
}
public void AdjustShortPath()
{
int column = 1;
while (column < nVerts)
// if (vertexList[column].isInTree)
// column++;
// else
{
int currentToFring = adjMat[currentVert, column];
int startToFringe = startToCurrent + currentToFring;
int sPathDist = sPath[column].distance;
if (startToFringe < sPathDist)
{
sPath[column].parentVert = currentVert;
sPath[column].distance = startToFringe;
}
column++;
}
}
public void DisplayPaths()
{
for (int j = 0; j <= nVerts - 1; j++)
{
Console.Write(vertexList[j].label + "=");
if (sPath[j].distance == infinity)
Console.Write("inf");
else
Console.Write(sPath[j].distance);
string parent = vertexList[sPath[j].parentVert].
label;
Console.Write("(" + parent + ") ");
}
}
}
public class DistOriginal
{
public int distance;
public int parentVert;
public DistOriginal(int pv, int d)
{
distance = d;
parentVert = pv;
}
}
*/
}
}結果截圖: