21 阅读2分钟

有向图的邻接表

代码实现

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <list>

using namespace std;

class Digraph {
public:
  // 从配置文件读取定点和边的信息,生成邻接表
  void readFile(string filePath) {
    FILE *pf = fopen(filePath.c_str(), "r");
    if (pf == nullptr) {
      perror("read file");
      throw "error";
    }

    // 占用第0号位置
    vertics.emplace_back("");

    while (!feof(pf)) {
      char line[1024] = {0};
      fgets(line, 1024, pf);  // 读取节点的信息

      // 增加一个节点信息
      string linestr(line);
      vertics.emplace_back(linestr.substr(0, linestr.size() - 1));

      fgets(line, 1024, pf);  // 读取边的信息
      char* vertic_no = strtok(line, ",");

      while (vertic_no != nullptr) {
        vertics.back().adjList_.emplace_back(atoi(vertic_no));
      
        vertic_no = strtok(nullptr, ",");
      }

    }

    fclose(pf);

  }

  // 输出邻接表信息
  void show() {
    for (int i = 1; i < vertics.size(); i++) {
      cout << vertics[i].data_ << ":";
      for (auto no : vertics[i].adjList_) {
        cout << no << " ";
      }
      cout << endl;
    }
    cout << endl;
  }

private:
  // 顶点类型
  struct Vertic {

    Vertic(string data): data_(data) {}

    string data_;  // 存储定点的信息
    list<int>  adjList_; // 邻接链表结构

  };
private:
  vector<Vertic> vertics; // 邻接表结构

};

int main() {

  Digraph graph;
  graph.readFile("data.txt");

  graph.show();

  return 0;
}

测试

data.txt文件内容

A
2,4,5
B
6
C
2,4
D
3,8
E
8
F
7,9
G
2,3
H
0
I
8
➜  有向图邻接表 git:(main) ✗ g++ main.cpp -o main
➜  有向图邻接表 git:(main) ✗ ./main              
A:2 4 5 
B:6 
C:2 4 
D:3 8 
E:8 
F:7 9 
G:2 3 
H:0 
I:8 

图的深度和广度优先遍历

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <queue>

using namespace std;

class Digraph {
public:
  // 从配置文件读取定点和边的信息,生成邻接表
  void readFile(string filePath) {
    FILE *pf = fopen(filePath.c_str(), "r");
    if (pf == nullptr) {
      perror("read file");
      throw "error";
    }

    // 占用第0号位置
    vertics.emplace_back("");

    while (!feof(pf)) {
      char line[1024] = {0};
      fgets(line, 1024, pf);  // 读取节点的信息

      // 增加一个节点信息
      string linestr(line);
      vertics.emplace_back(linestr.substr(0, linestr.size() - 1));

      fgets(line, 1024, pf);  // 读取边的信息
      char* vertic_no = strtok(line, ",");

      while (vertic_no != nullptr) {

        int vex = atoi(vertic_no);
        if (vex > 0) {
          vertics.back().adjList_.emplace_back(atoi(vertic_no));
        }
      
        vertic_no = strtok(nullptr, ",");
      }

    }

    fclose(pf);

  }

  // 输出邻接表信息
  void show() {
    for (int i = 1; i < vertics.size(); i++) {
      cout << vertics[i].data_ << ":";
      for (auto no : vertics[i].adjList_) {
        cout << no << " ";
      }
      cout << endl;
    }
    cout << endl;
  }

  // 图的深度优先遍历
  void dfs() {
    vector<bool> visited(vertics.size(), false);
    dfs(1, visited);
    cout << endl;
  }
    // 广度优先遍历
  void bfs() {
    vector<bool> visited(vertics.size(), false);  // 标识当前节点是否被遍历过

    queue<int> que;

    que.push(1);
    visited[1] = true;

    while (!que.empty()) {
      int cur_no = que.front();
      que.pop();

      cout << vertics[cur_no].data_ << " ";

      for (auto no : vertics[cur_no].adjList_) {
        if (!visited[no]) {
          que.push(no);
          visited[no] = true;
        }
      }

    }

    cout << endl;

  }
private:

  // 深度优先遍历的递归接口
  void dfs(int start, vector<bool>& visited) {

    if (visited[start]) {
      return;  // 已经遍历过了
    }

    cout << vertics[start].data_ << " ";
    visited[start] = true;

    // 递归遍历下一层节点
    for (auto no : vertics[start].adjList_) {
      dfs(no, visited);
    }
  }

private:
  // 顶点类型
  struct Vertic {

    Vertic(string data): data_(data) {}

    string data_;  // 存储定点的信息
    list<int>  adjList_; // 邻接链表结构

  };
private:
  vector<Vertic> vertics; // 邻接表结构

};

int main() {

  Digraph graph;
  graph.readFile("data.txt");

  graph.show();

  graph.dfs();

  graph.bfs();

  return 0;
}

测试

➜  有向图邻接表 git:(main) ✗ ./main              
A:2 4 5 
B:6 
C:2 4 
D:3 8 
E:8 
F:7 9 
G:2 3 
H:
I:8 

A B F G C D H I E 
A B D E F C H G I