1. 程式人生 > >簡單無向圖(c++版)

簡單無向圖(c++版)

Graph.h

#pragma once
#include <string>
#include <sstream>
#include <fstream>
#include <iterator>
#include <stack>
#include <queue>

class Graph
{
private:
    class EdgeList
    {
    public:
        class Node
        {
        public:
            int link;
            Node* next = nullptr;
        public
: Node(const int& n) :link(n) { } }; Node* head = nullptr; public: class Iterator { private: Node* it; public: Iterator(Node* i) :it(i) {} Iterator operator++() { it = it->next; return
*this; } Iterator operator++(int) { Node* i = it; it = it->next; return Iterator(i); } bool operator == (const Iterator& rhs) { if (it == nullptr && rhs.it == nullptr) return
true; if (it != nullptr && rhs.it != nullptr) { if (it == rhs.it) return true; } return false; } bool operator != (const Iterator& rhs) { return !(*this == rhs); } const int& operator *() { if (it == nullptr) throw std::logic_error("* nullptr error"); return it->link; } }; /****************************************** 函式名稱: begin 函式說明: 返回迭代器begin位置 *******************************************/ Iterator begin()const { return Iterator(head); } /****************************************** 函式名稱: end 函式說明: 返回迭代器尾部也就是nullptr 返回值 Iterator *******************************************/ Iterator end()const { return Iterator(nullptr); } /****************************************** 函式名稱: addNode 函式說明: 給鄰接表增加節點 返回值: void *******************************************/ void addNode(const int& link) { if (head == nullptr) { head = new Node(link); return; } Node* curr = head; while (curr->next != nullptr) curr = curr->next; curr->next = new Node(link); return; } }; private: int V; int E; EdgeList* adj; public: Graph(const std::string& file) { std::ifstream in(file); std::istream_iterator<int> beg(in); std::istream_iterator<int> end; V = *beg; adj = new EdgeList[V]; for (auto it = ++beg; it != end; ++it) { int pre = *it; int curr = *++it; adj[pre].addNode(curr); adj[curr].addNode(pre); ++E; } } /****************************************** 函式名稱: degree 函式說明: 計算結點v的度數 返回值: int *******************************************/ int degree(const int& v) { if (v > V - 1) throw std::out_of_range("結點超出範圍"); int count = 0; for (auto &i : adj[v]) ++count; return count; } /****************************************** 函式名稱: max_degree 函式說明: 計算所有頂點的最大度數 返回值: int *******************************************/ int max_degree() { int max = 0; for (int i = 0; i < V; ++i) if (degree(i) > max) max = degree(i); return max; } /****************************************** 函式名稱: avge_degree 函式說明: 計算所有頂點的平均度數 返回值: double *******************************************/ double avge_degree() { if (V == 0) return 0.0; return 2 * E / V; } /****************************************** 函式名稱: numSelfLoops 函式說明: 計算自環的個數 返回值: int *******************************************/ int numSelfLoops() { int count = 0; for (int i = 0; i < V; ++i) for (auto& w : adj[i]) if (i == w) ++count; return count; } /****************************************** 函式名稱: ncount 函式說明: 返回圖的結點個數 返回值: int *******************************************/ int ncount() { return V; } /****************************************** 函式物件(有狀態的函式) 生成用於連通性,是否連通,連通結點個數等演算法 *******************************************/ class DeepFirstSearch { private: bool *marked; int count; Graph *g; int **edgeTo; int *id; int nconnect; private: void init() { for (int i = 0; i < g->ncount(); ++i) { marked[i] = false; edgeTo[i] = nullptr; } count = 0; } public: DeepFirstSearch(Graph* g):g(g),count(0),nconnect(0) { marked = new bool[g->ncount()]; edgeTo = new int*[g->ncount()]; id = new int[g->ncount()]; init(); } void dfs(const int& s,std::string mode = "no") { if (mode == "display") std::cout << s << "----"; marked[s] = true; ++count; id[s] = nconnect; for (auto &w : g->adj[s]) if (!marked[w]) { edgeTo[w] = new int(s); dfs(w,mode); } } /****************************************** 函式名稱: isLink 函式說明: 判斷兩節點是否連通 返回值: bool *******************************************/ bool isLink(const int& s, const int& e) { init(); dfs(s); return marked[e]; } /****************************************** 函式名稱: display 函式說明: 列印一條該節點在圖中的通路 返回值 void *******************************************/ void display(const int& s) { dfs(s, "display"); } int size(const int& s) { init(); dfs(s); return count; } /****************************************** 函式名稱: manyConnect 函式說明: 計算圖中有多少連通圖 返回值: int ******************************************/ int manyConnect() { init(); for (int i = 0; i < g->ncount(); ++i) { if (!marked[i]) { ++nconnect; dfs(i); } } return nconnect; } /***************************************** 函式名稱: printConnect 函式說明: 列印連通圖 返回值: void ******************************************/ void printConnect() { manyConnect(); for (int i = 1; i <= nconnect; ++i) { std::cout << "第" << i << "幅連通圖 : "; for (int j = 0; j < g->ncount(); ++j) { if (id[j] == i) std::cout << j << "--"; } std::cout << std::endl; } } /****************************************** 函式名稱: printPath 函式說明: 列印起點s到終點e的一條路徑 返回值: void *******************************************/ void printPath(const int& s,const int& e) { init(); dfs(s); std::stack<int> sk; for (int* i = edgeTo[e]; i != nullptr; i = edgeTo[*i]) sk.push(*i); bool flag = sk.empty(); while (!sk.empty()) { std::cout << sk.top() << "--->"; sk.pop(); } if (!flag) std::cout << e << std::endl; } ~DeepFirstSearch() { if (marked != nullptr) delete marked; if (edgeTo != nullptr) delete edgeTo; } }; //應用於圖 int count(const int& s) { DeepFirstSearch Dfs(this); return Dfs.size(s); } void display(const int& s) { DeepFirstSearch(this).display(s); } bool isLink(const int& s, const int& e) { return DeepFirstSearch(this).isLink(s, e); } void printPath(const int& s,const int& e) { return DeepFirstSearch(this).printPath(s, e); } int manyConnect() { return DeepFirstSearch(this).manyConnect(); } void printConnect() { DeepFirstSearch(this).printConnect(); } private: class BreadthFirstSearch { private: bool* masked; int count; int** edgeTo; Graph* g; void init() { for (int i = 0; i < g->ncount(); ++i) { masked[i] = false; edgeTo[i] = nullptr; } } public: BreadthFirstSearch(Graph *g):g(g) { masked = new bool[g->ncount()]; edgeTo = new int*[g->ncount()]; } void bfs(const int& s) { std::queue<int> q; q.push(s); masked[s] = true; while (!q.empty()) { for (auto& w : g->adj[q.front()]) { if (!masked[w]) { edgeTo[w] = new int(q.front()); masked[w] = true; q.push(w); } } q.pop(); } } /****************************************** 函式名稱: shortestPath 函式說明: 得到起點s到e的最短路徑 返回值: void *******************************************/ void shortestPath(const int& s,const int& e) { init(); bfs(s); std::stack<int> sk; sk.push(e); for (int* i = edgeTo[e]; i != nullptr; i = edgeTo[*i]) { sk.push(*i); if (*i == s) break; } if (sk.top() != s) return; while (!sk.empty()) { if (sk.top() != e) std::cout << sk.top() << "--->"; else std::cout << sk.top(); sk.pop(); } } }; public: void shortestPath(const int& s, const int& e) { BreadthFirstSearch(this).shortestPath(s, e); } };

main.cpp

#include <iostream>
#include "Graph.h"
using namespace std;

int main()
{
    Graph g("test.txt");
    cout << "結點0的度數為: " << g.degree(0) << endl;
    cout << "最大度數為: " << g.max_degree() << endl;
    cout << "平均度數為: " << g.avge_degree() << endl;
    cout << "自環個數為: " << g.numSelfLoops() << endl;
    cout << "與0能連通的結點個數為: " << g.count(0) << endl;
    cout << "0 與 9 能連通嗎? :" << (g.isLink(0, 9) ? "能" : "不能") << endl;
    cout << "列印0的一條連線序列: " << endl;
    g.display(0);
    cout << "列印0到6的連線序列: " << endl;
    g.printPath(0, 6);
    cout << "列印0到6的最短路徑: " << endl;
    g.shortestPath(9, 12);
    cout << endl;
    cout << "有多少連通圖: " << g.manyConnect();
    cout << endl;
    cout << "列印連通圖: " << endl;
    g.printConnect();
    system("pause");
    return 0;
}

測試檔案: test.txt

13
0 5
4 3
0 1
9 12
6 4
5 4
0 2
11 12
9 10
0 6
7 8
9 11
5 3

執行:

這裡寫圖片描述

相關推薦

簡單(c++)

Graph.h #pragma once #include <string> #include <sstream> #include <fstream> #include <iterator> #include

Codeforces 11D A Simple Task 統計簡單中環的個數

題目表述 Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no repeated vertices or edges.

演算法 中求最小環路徑 最小環個數 最大平均環 求簡單中環的個數

最小環問題:求個圖中環路徑代價最小的迴路。 如何求最小環?假如有 路徑1->3->2,如果此時已經知道2-1的最短路徑就好了。 回想下floyed的更新過程,就會發現更新第k次時,比k小的點之間都是最短距離的(要是點是聯通的話)。所以給出解法:第k次更新圖時

POJ 3710 簡單環樹上刪邊

author first != fine 如何 class 轉換 hub memset 結論題,這題關鍵在於如何轉換環,可以用tarjan求出連通分量後再進行標記,也可以DFS直接找到環後把點的SG值變掉就行了 /** @Date : 2017-10-23 19:4

C語言利用的鄰接矩陣的儲存方式實現有的深度優先搜尋(DFS)

C語言利用圖的鄰接矩陣的儲存方式實現有向圖和無向圖的深度優先搜尋(DFS) Description 圖採用鄰接矩陣儲存,圖中頂點數為n(0<n<20),頂點資訊為整數,依次為0,1,..,n-1。 編寫函式,輸入圖的型別,0:無向圖,1:有向圖;輸入圖的頂點數、邊數、邊的偶對

C語言利用的鄰接矩陣的儲存方式實現有的廣度優先搜尋(BFS)

#include <stdio.h> #include <stdlib.h> #define Max_Vetex_Num 100 #define MAXSIZE 20 #define STACK_SIZE 30 typedef struct { int vexs[M

C語言利用的鄰接表的儲存方式實現求有的入度和出度以及的度數

Description 圖採用鄰接表為儲存結構,圖中的頂點數為n(0<n<=20),n個頂點的資訊依次為 0,1,...,n-1。 編寫程式,輸入圖的型別(0:無向圖,1:有向圖)、圖中頂點數、邊數、邊的偶對,建立圖的鄰接表。如果是無向圖,計算並輸出每個頂點的度;如果是有向圖,計

C語言實現鄰接矩陣建立&的深度優先遍歷

/* '鄰接矩陣' 實現無向圖的建立、深度優先遍歷*/ #include <stdio.h> #include <stdlib.h> #define MaxVex 100 //最多頂點個數 #define INFINITY 32768

鄰接矩陣(二)之 C++詳解

/* * 建立圖(自己輸入資料) */ MatrixUDG::MatrixUDG() { char c1, c2; int i, p1, p2; // 輸入"頂點數"和"邊數" cout << "input vertex number:

鄰接表(一)之 C語言詳解

/* * 建立鄰接表對應的圖(自己輸入) */ LGraph* create_lgraph() { char c1, c2; int v, e; int i, p1, p2; ENode *node1, *node2; LGraph* pG;

鄰接矩陣(一)之 C語言詳解

/* * 建立圖(用已提供的矩陣) */ Graph* create_example_graph() { char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; char edges[][2] = { {'A'

鄰接表(二)之 C++詳解

/* * 建立鄰接表對應的圖(自己輸入) */ ListUDG::ListUDG() { char c1, c2; int v, e; int i, p1, p2; ENode *node1, *node2; // 輸入"頂點數"和"邊數"

-鄰接矩陣-寬度優先遍歷-BFS C程式碼實現

一、BFS演算法思路本演算法以無向圖為例,儲存方式採用鄰接矩陣1)將該網以鄰接矩陣的方式儲存,由於這裡的示例採用無向圖,因此它是一個對稱陣2)選取A點為起始點,訪問此頂點,用一個visit的bool型陣列記錄訪問狀態(false表示未被訪問,true表示已訪問)3)從A的未被

c++編寫 使用容器Vector編寫鄰接表法

對於無向圖的編寫,傳統方法有兩種: 1、鄰接矩陣法(適合邊數多的無向圖)。 2、鄰接表法(適合邊數較少的無向圖)。 在我轉載的兩篇無向圖編寫的部落格中已經詳細介紹過了。 但是使用鄰接表法時總感覺程式

判斷是不是連通的c++程式碼

// DFS.cpp : 定義控制檯應用程式的入口點。// #include "stdafx.h"#include <iostream>#include <vector>using namespace std;bool isconnected(vect

判別中任意給定的2個頂點之間是否存在一條長度 為k的簡單路徑

判別無向圖中任意給定的2個頂點之間是否存在一條長度 為k的簡單路徑  無向圖是沒有權值的這裡的k值代表經歷k-1個頂點 不要以為很簡單,裡面很niu的  int visited[MAXSIZE] /

廣度優先遍歷 c語言實現

這裡記錄一下無向圖的廣度優先遍歷,無向圖用鄰接表表示,使用的圖的示例圖如下,關於圖的表示可以參照部落格:無向圖的表示:鄰接矩陣和鄰接表,這裡不再贅述,無向圖的表示的程式碼被封裝到標頭檔案queue.h

深度優先遍歷 c語言實現

無向圖的深度優先遍歷的實現,無向圖用鄰接表表示無向圖的表示:鄰接矩陣和鄰接表。 程式使用的示例圖為: 實現要點: 每個節點有三種狀態: -1,還未發現 0,已經發現了,正在處理,還沒有處理

java的深度優先搜尋,求連通個數

package ctong; import java.util.Arrays; import java.util.Random; public class Graph_DFS { /** * Ctong * @param args */ //建立一個標

(有)的鄰接矩陣表示C++實現(遍歷,拓撲排序,最短路徑,最小生成樹) Implement of digraph and undigraph using adjacency matrix

本文實現了有向圖,無向圖的鄰接矩陣表示,並且實現了從建立到銷燬圖的各種操作。 以及兩種圖的深度優先遍歷,廣度優先遍歷,Dijkstra最短路徑演算法,Prim最小生成樹演算法,有向圖的拓撲排序演算法。 通過一個全域性變數控制當前圖為有向圖還是無向圖。 若為無向圖,則生成的