重新整理資料結構與演算法(c#)—— 圖的深度遍歷和廣度遍歷[十一]
參考網址:https://www.cnblogs.com/aoximin/p/13162635.html
前言
簡介圖:
在資料的邏輯結構D=(KR)中,如果K中結點對於關係R的前趨和後繼的個數不加限制,即僅含一種任意的關係,則稱這種資料結構為圖形結構。
來源百度百科
圖形結構是一種比樹形結構更復雜的非線性結構。在樹形結構中,結點間具有分支層次關係,每一層上的結點只能和上一層中的至多一個結點相關,但可能和下一層的多個結點相關。而在圖形結構中,任意兩個結點之間都可能相關,即結點之間的鄰接關係可以是任意的
然後就是盜圖階段:
後面就是一些基礎常識,我找到一個比較全的:
https://www.cnblogs.com/songgj/p/9107797.html
正文
那麼就來看一下圖的深度遍歷和廣度遍歷吧。
先來定義一個圖:
public class Graph
{
private List<String> vertexList; //儲存頂點集合
private int[,] edges; //儲存圖對應的鄰結矩陣
private Boolean[] isVisited;// 判斷是否訪問了
int numOfEdges;
public Graph(int n){
vertexList = new List<string>();
edges = new int[8, 8];
isVisited = new Boolean[8];
}
/// <summary>
/// 增加節點
/// </summary>
/// <param name="vertex">節點</param>
public void addVertex(string vertex)
{
vertexList.Add(vertex);
}
public void insertEdge(int x,int y,int weight)
{
//增加他們的連線 且設定他們的權重
edges[x, y] = 1;
edges[y, x] = 1;
numOfEdges++;
}
public void showEdges()
{
for (int i=0;i< isVisited.Length;i++)
{
for (int j = 0; j < isVisited.Length; j++)
{
Console.Write(edges[i,j]+" ");
}
Console.WriteLine();
}
}
}
測試一下:
String[] Vertexs = { "1", "2", "3", "4", "5", "6", "7", "8" };
//建立圖物件
Graph graph = new Graph(Vertexs.Count());
//迴圈的新增頂點
foreach (String vertex in Vertexs)
{
graph.addVertex(vertex);
}
//更新邊的關係
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.insertEdge(3, 7, 1);
graph.insertEdge(4, 7, 1);
graph.insertEdge(2, 5, 1);
graph.insertEdge(2, 6, 1);
graph.insertEdge(5, 6, 1);
graph.showEdges();
Console.ReadKey();
結果:
這麼看可能不清晰哈,那麼我畫個圖,看一下。
這是下面這張圖哈:
深度遍歷:
private int getFirstNeighbor(int index)
{
for (int j = 0; j < isVisited.Length; j++)
{
if (edges[index, j] > 0)
{
return j;
}
}
return -1;
}
/// <summary>
/// 通過鄰接節點來獲取下一個節點
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
public int getNextNeighbor(int v1, int v2)
{
for (int j = v2+1; j < isVisited.Length; j++)
{
if (edges[v1, j] > 0)
{
return j;
}
}
return -1;
}
/// <summary>
/// 深度遍歷
/// </summary>
/// <param name="i"></param>
public void dfs(int i)
{
//列印遍歷的值
Console.Write(vertexList[i]+" ");
isVisited[i] = true;
int w = getFirstNeighbor(i);
while (w != -1)
{
if (!isVisited[w])
{
dfs(w);
}
w = getNextNeighbor(i,w);
}
}
然後呼叫函式:
graph.dfs(0);
得到的結果是:
看下廣度遍歷吧:
//對一個結點進行廣度優先遍歷的方法
public void bfs(int i)
{
//列印遍歷的值
Console.Write(vertexList[i] + " ");
LinkedList<int> queue = new LinkedList<int>();
queue.AddLast(i);
int u;
while (queue.Count != 0)
{
u = queue.First.Value;
queue.RemoveFirst();
int w = getFirstNeighbor(i);
while (w != -1)
{
if (!isVisited[w])
{
Console.Write(vertexList[w] + " ");
isVisited[w] = true;
queue.AddLast(w);
}
w = getNextNeighbor(u, w);
}
}
}
然後呼叫:
Console.WriteLine("廣度遍歷");
graph.bfs(0);
結果:
//自己編寫的程式碼 僅供參考
publicclassNode<T>
{
publicboolaccessed = false;
publicT t;
}
publicclassMyGrapic<T>
{
privateNode<T>[] arryNode = null;
privateint[,] Matrix = null;
privateintnum;
publicMyGrapic(Node<T>[] arrn)
{
arryNode = arrn;
varn = arrn.Length;
Matrix = newint[n, n];
this.num = n;
this.initMatix();
}
privatevoidinitMatix()
{
for(inti = 0; i < this.num; i++)
{
for(intj = 0; i < this.num; i++)
{
Matrix[i, j] = 0;
}
}
}
publicvoidSetEdget(Node<T> n1, Node<T> n2)
{
intindex1 = findNode(n1);
intindex2 = findNode(n2);
Matrix[index1, index2] = 1;
Matrix[index2, index1] = 1;
}
privateintfindNode(Node<T> n)
{
intindex = -1;
for(inti = 0; i < this.num; i++)
{
vara = arryNode[i]; index++;
if(a.Equals(n))
{
returni;
}
}
returnindex;
}
publicvoidPrintMatix()
{
for(inti = 0; i < this.num; i++)
{
for(intj = 0; j < this.num; j++)
{
Console.Write("{0} ", Matrix[i, j]);
}
Console.WriteLine();
}
}
privateNode<T> findNeighbor(Node<T> node)
{
intindex1 = findNode(node);
intindex2 = -1;
for(inti = 0; i < this.num; i++)
{
if(Matrix[index1, i] == 1)
{
if(arryNode[i].accessed == false)
{
index2 = i;
break;
}
}
}
if(index2 == -1)
{
returnnull;
}
returnarryNode[index2];
}
///<summary>
///通過鄰接節點來獲取下一個節點
///</summary>
///<paramname="node1"></param>
///<paramname="node2"></param>
///<returns></returns>
privateNode<T> findNeighbor2(Node<T> node1, Node<T> node2)
{
intindex1 = findNode(node1);
intj = findNode(node2);
intindex2 = -1;
for(inti = j; i < this.num; i++)
{
if(Matrix[index1, i] == 1)
{
if(arryNode[i].accessed == false)
{
index2 = i;
break;
}
}
}
if(index2 == -1)
{
returnnull;
}
returnarryNode[index2];
}
publicvoidDSF(Node<T> node)
{
if(node.accessed == true)
{
return;
}
Console.Write("{0}\t", node.t);
node.accessed = true;
varneighbor = findNeighbor(node);
while(neighbor != null)
{
DSF(neighbor);
neighbor = findNeighbor2(node, neighbor);
}
}
}