1. 程式人生 > 其它 >重新整理資料結構與演算法(c#)—— 圖的深度遍歷和廣度遍歷[十一]

重新整理資料結構與演算法(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);

}

}

}