資料結構學習(C++)——圖【2】(DFS和BFS) (轉)

amyz發表於2007-11-13
資料結構學習(C++)——圖【2】(DFS和BFS) (轉)[@more@]

對於非線性的結構,遍歷都會首先成為一個問題。和二叉樹的遍歷一樣,圖也有深度優先搜尋(DFS)和廣度優先搜尋(BFS)兩種。不同的是,圖中每個頂點沒有了祖先和子孫的關係,因此,前序、中序、後序不再有意義了。仿照二叉樹的遍歷,很容易就能完成DFS和BFS,只是要注意圖中可能有迴路,因此,必須對訪問過的頂點做標記。

最基本的有向帶權網

#ifndef Graph_H

#define Graph_H

 :namespace prefix = o ns = "urn:schemas--com::office" />

#include

#include

using namespace std;

#include "Graphmem.h"

 

template

classwork

{

public:

  Network() {}

  Network(dist maxdist) { data.NoEdge = maxdist; }

 work() {}

  bool insertV(name v) { return data.insertV(v); }

  bool insertE(name v1, name v2, dist cost) { return data.insertE(v1, v2, cost); }

  name& getV(int n) { return data.getV(n); }

  int nextV(int m, int n = -1) { return data.nextV(m, n); }

  int vNum() { return data.vNum; }

  int eNum() { return data.eNum; }

protected:

  bool* visited;

  static void print(name v) { cout << v; }

private:

  mem data;

};

#endif

你可以看到,這是在以mem方式儲存的data上面加了一層外殼。在圖這裡,邏輯上分有向、無向,帶權、不帶權;儲存結構上有鄰接矩陣和鄰接表。也就是說分開來有8個類。為了最大限度的複用程式碼,繼承關係就非常複雜了。但是,多重繼承是件很討厭的事,什麼覆蓋啊,還有什麼虛擬繼承,我可不想花大量篇幅講語言特性。於是,我將儲存方式作為第三個模板引數,這樣一來就省得涉及虛擬繼承了,只是這樣一來這個Network的例項化就很麻煩了,不過這可以透過typedef或者外殼類來解決,我就不寫了。反正只是為了讓大家明白,真正要用的時候,最好是寫專門的類,比如無向無權鄰接矩陣圖,不要搞的繼承關係亂七八糟。

DFS和BFS的實現

public:

  void DFS(void(*visit)(name v) = print)

  {

  visited = new bool[vNum()];

  for (int i = 0; i < vNum(); i++) visited[i] = false;

  DFS(0, visit);

  delete []visited;

  }

protected:

  void DFS(int i, void(*visit)(name v) = print)

  {

    visit(getV(i)); visited[i] = true;

  for (int n = nextV(i); n != -1; n = nextV(i, n))

  if (!visited[n]) DFS(n, visit);

  }

public:

  void BFS(int i = 0, void(*visit)(name v) = print)//n沒有越界檢查

  {

  visited = new bool[vNum()]; queue a; int n;

  for (n = 0; n < vNum(); n++) visited[n] = false;

    visited[i] = true;

  while (i != -1)//這個判斷可能是無用的

  {

    visit(getV(i));

    for (n = nextV(i); n != -1; n = nextV(i, n))

    if (!visited[n]) { a.push(n); visited[n] = true; }

  if (a.empty()) break;

  i = a.front(); a.pop();

  }

  delete []visited;

  }

DFS和BFS很難寫得像樹的遍歷方法那麼通用,這在後面就會看到,雖然我們使用了DFS和BFS的思想,但是上面的函式卻不能直接使用。因為樹的資訊主要在節點上,而圖的邊上還有資訊。

測試

#include

using namespace std;

#include "Graph.h"

int main()

{

  Network > a;

  a.insertV('A'); a.insertV('B');

  a.insertV('C');  a.insertV('D');

  a.insertE('A', 'B', 1); a.insertE('A', 'C', 2);

  a.insertE('B', 'D', 3);

  cout << "DFS: "; a.DFS(); cout << endl;

  cout << "BFS: "; a.BFS(); cout << endl;

  return 0;

}

老實說,這個類用起來真的不是很方便。不過能說明問題就好。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-982214/,如需轉載,請註明出處,否則將追究法律責任。

相關文章