template
class Network {
public:
using VertexRef = Vertex&;
using ConstVertexRef = const Vertex&;
Network() = default;
explicit Network(Weight no_edge) : storage_(no_edge) {}
bool insertV(ConstVertexRef v) { return storage_.insertV(v); }
bool insertE(ConstVertexRef u, ConstVertexRef v, Weight w) { return storage_.insertE(u, v, w); }
ConstVertexRef getV(size_t idx) const { return storage_.getV(idx); }
size_t nextV(size_t from, size_t prev = npos) const { return storage_.nextV(from, prev); }
size_t vNum() const { return storage_.vNum(); }
size_t eNum() const { return storage_.eNum(); }
// DFS / BFS 介面
template
void DFS(Visit visit = Print) { dfs_impl(visit); }
template
void BFS(Visit visit = Print) { bfs_impl(visit); }
private:
Storage storage_;
std::vector visited_;
static constexpr size_t npos = static_cast(-1);
template
void dfs_impl(Visit visit) {
visited_.assign(vNum(), false);
if (vNum()) dfs_recursive(0, visit);
}
template
void dfs_recursive(size_t idx, Visit visit) {
visit(getV(idx));
visited_[idx] = true;
for (size_t n = nextV(idx); n != npos; n = nextV(idx, n)) {
if (!visited_[n]) dfs_recursive(n, visit);
}
}
template
void bfs_impl(Visit visit) {
visited_.assign(vNum(), false);
std::queue q;
if (vNum()) {
visited_[0] = true;
q.push(0);
}
while (!q.empty()) {
size_t cur = q.front(); q.pop();
visit(getV(cur));
for (size_t n = nextV(cur); n != npos; n = nextV(cur, n)) {
if (!visited_[n]) {
visited_[n] = true;
q.push(n);
}
}
}
}
template
static void Print(ConstVertexRef v) { std::cout << v << ' '; }
};
template
class AdjMatrix {
std::vector vertices_;
std::vector> matrix_;
Weight no_edge_;
public:
explicit AdjMatrix(Weight no_edge) : no_edge_(no_edge) {}
bool insertV(ConstVertexRef v) {
vertices_.push_back(v);
for (auto& row : matrix_) row.push_back(no_edge_);
matrix_.emplace_back(vertices_.size(), no_edge_);
return true;
}
bool insertE(ConstVertexRef u, ConstVertexRef v, Weight w) {
auto iu = find_idx(u), iv = find_idx(v);
if (iu == npos || iv == npos) return false;
matrix_[iu][iv] = w;
return true;
}
// getV, nextV, vNum, eNum 實現略...
};
template
struct Edge { Vertex to; Weight w; size_t next; };
template
class AdjList {
std::vector vertices_;
std::vector> edges_;
std::vector head_;
Weight no_edge_;
public:
explicit AdjList(Weight no_edge) : no_edge_(no_edge) {}
bool insertV(ConstVertexRef v) {
vertices_.push_back(v);
head_.push_back(npos);
return true;
}
bool insertE(ConstVertexRef u, ConstVertexRef v, Weight w) {
auto iu = find_idx(u), iv = find_idx(v);
if (iu == npos || iv == npos) return false;
edges_.push_back({v, w, head_[iu]});
head_[iu] = edges_.size() - 1;
return true;
}
// getV, nextV (遍歷 edges_[head_[idx]] 鏈表), vNum, eNum 實現略...
};
int main() {
using Graph = Network>;
Graph g(INT_MAX); // 無邊權重用 INT_MAX
g.insertV('A'); g.insertV('B'); g.insertV('C'); g.insertV('D');
g.insertE('A', 'B', 1);
g.insertE('A', 'C', 2);
g.insertE('B', 'D', 3);
std::cout << "DFS: "; g.DFS(); std::cout << '\n'; // 預期: A B D C (或 A C B D 視插入順序)
std::cout << "BFS: "; g.BFS(); std::cout << '\n'; // 預期: A B C D
return 0;
}
| 操作 | 鄰接矩陣 | 鄰接表 |
|---|---|---|
| 空間 | O(V²) | O(V+E) |
| 判斷邊存在 | O(1) | O(deg(u)) |
| 遍歷鄰邊 | O(V) | O(deg(u)) |
| 插入頂點 | O(V) (擴容) | O(1) 擴展 |
| 適用場景 | 稠密圖 (E ≈ V²)、頻繁查邊 | 稀疏圖 (E ≪ V²)、大規模圖 |
**模板化儲存策略 + 訪問器演算法** 是 C++ 實現圖庫的經典範式。**避免多重繼承,採用策略模式 (Policy-based Design)**,既獲得零開銷抽象,又保持程式碼清晰可維護。下一步將實現 MST、最短路徑、拓撲排序,敬請期待。