C++_图


邻接矩阵

//
// Created by zhou on 2023/10/11.
//
#include "../utils/common.h"

class GraphAdjMat {
    // 顶点表,元素代表顶点值,索引代表顶点索引
    vector<int> vertices;
    // 邻接矩阵,行列索引对应顶点索引(边连接的两顶点索引)
    vector<vector<int>> adjMat;

public:
    GraphAdjMat(const vector<int> &vertices, const vector<vector<int>> &edges) {
        // vector<int> vertices = {1, 3, 2, 5, 4};
        for (int val : vertices) {
            addVertex(val);
        }
        for (const vector<int> &edge: edges) {
            // ?? 为什么是 0 1 索引
            // 示例:vector<vector<int>> edges = {{0, 1}, {0, 3}, {1, 2}, {2, 3}, {2, 4}, {3, 4}};
            // edges存的是顶点索引,[i][j]表示的是i到j的边
            addEdge(edge[0], edge[1]);
        }
    }

    int size() const {
        return vertices.size();
    }

    /**
     * 添加顶点
     */
    void addVertex(int val) {
        int n = size();
        // 将顶点入列表
        vertices.push_back(val);
        // 矩阵新建一行
        adjMat.emplace_back(vector<int>(n, 0));
        // 矩阵新建一列
        for (vector<int> &rows : adjMat) {
            rows.push_back(0);
        }
    }

    /**
     * 添加边
     */
    void addEdge(int i, int j) {
        if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) {
            throw out_of_range("顶点不存在");
        }
        // 无向图,关于主对角线对称
        adjMat[i][j] = 1;
        adjMat[j][i] = 1;
    }

    /**
     * 删除顶点
     */
    void removeVertex(int index) {
        if(index >= size()) throw out_of_range("顶点不存在");
        // 删除顶点
        vertices.erase(vertices.begin() + index);
        // 删除对应的行
        adjMat.erase(adjMat.begin() + index);
        // 删除对应的列
        for (vector<int> &rows: adjMat) {
            rows.erase(rows.begin() + index);
        }
    }

    void removeEdge(int i, int j) {
        if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) {
            throw out_of_range("顶点不存在");
        }
        // 无向图,关于主对角线对称
        adjMat[i][j] = 0;
        adjMat[j][i] = 0;
    }
};

邻接表

//
// Created by zhou on 2023/10/13.
//
#include "../utils/common.h"

class GraphAdjacencyList{
public:
    // key:是顶点,value:是对应的链表(即所有邻接节点)
    unordered_map<Vertex *, vector<Vertex *>> adjList;

    // 删除对应的顶点和边(邻接表中边其实依赖于顶点,把各自的顶点删除,就相当于把两点之间的边删除了)
    void remove(vector<Vertex *> vec, Vertex *vet) {
        for (int i = 0; i < vec.size(); ++i) {
            if (vec[i] == vet) vec.erase(vec.begin() + i);
            break;
        }
    }

    // ??
    GraphAdjacencyList(const vector<vector<Vertex *>> &edges) {
        // 添加所有的顶点和边
        for(const vector<Vertex *> &edge : edges) {
            addVertex(edge[0]);
            addVertex(edge[1]);
            addEdge(edge[0], edge[1]);
        }
    }

    int size() {
        return adjList.size();
    }

    /**
     * 添加顶点
     */
    void addVertex(Vertex *vet) {
        // 已有顶点,直接结束。不能重复
        if (adjList.count(vet)) return;
        // 未有顶点,在新顶点后面新建链表
        adjList[vet] = vector<Vertex *>();
    }

    /**
     * 添加边
     */
    void addEdge(Vertex *vet1, Vertex *vet2) {
        // 没有相应的顶点或者是同一个顶点,异常处理
        if(!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2) {
            throw invalid_argument("顶点不存在");
        }
        // 添加相应的边,即在对应的链表中分别加入其节点
        adjList[vet1].push_back(vet2);
        adjList[vet2].push_back(vet1);
    }

    /**
     * 删除顶点
     */
    void removeVertex(Vertex *vet) {
        // 没有相应的顶点,无需删除
        if(!adjList.count(vet)) throw invalid_argument("顶点不存在");
        // 删除头节点及其边,相当于删除头节点及其后面的链表
        adjList.erase(vet);
        // second是找value,first找key;
        // 遍历剩余的顶点及后面的链表,找到与要删除的顶点,将其删除
        for (auto &item: adjList) {
            remove(item.second, vet);
        }
    }

    /**
     * 删除边
     */
    void removeEdge(Vertex *vet1, Vertex *vet2) {
        if(!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2) {
            throw invalid_argument("顶点不存在");
        }
        // 将其从对方的链表中删除,即实现了删除边
        remove(adjList[vet1], vet2);
        remove(adjList[vet2], vet1);
    }
};

评论
  目录