图的创建和遍历(邻接表、邻接矩阵存储实现BFS、DFS)

图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。在学习图的过程中,知道图中存储的数据称为顶点,无向图连接顶点之间关系的称为边,有向图连接顶点的称为弧,弧的起点为弧尾,终点为弧头。图可以根据边有无方向,分为无向图和有向图,只要存在有方向的边,则为有向图,全部为无方向边的图,则为无向图。

1.邻接表

接表是图的一种链式存储结构。由两部分组成:表头结点表和边表。邻接表中每个单链表的第一个结点存放有关顶点的信息,把这一结点看成链表的表头,其余结点存放有关边的信息

(1)表头结点表:包括数据域和链域,数据域存储顶点的名称,链域用于指向链表中第一个结点(与顶点邻接的第一个顶点)

(2)边表:包括邻接点域(指示与顶点邻接的点在图中的位置,即数组下标)、数据域(存储和边相关的信息,如权值)、链域(指示与顶点邻接的下一条边的结点)。

代码设计如下:

//
// Created by A on 2023/6/10.
//
#include <iostream>
#include <vector>
#include <cassert>
#include <stack>
#include <queue>
#include <algorithm>

using namespace std;

class SparseGraph {
public:
    int n, m;
    bool directed;
    vector<vector<int> > g;

    SparseGraph(int n, bool directed) {
        this->n = n;
        this->m = m;
        this->directed = directed;
        for (int i = 0; i < n; ++i)
            g.push_back(vector<int>());
    }

    ~SparseGraph() {

    }

    int V() {
        return n;
    }

    int E() {
        return m;
    }

    void addEgde(int v, int w) {
        assert(v >= 0 && v < n);
        assert(w >= 0 && w < n);
        g[v].push_back(w);
        if (!directed)
            g[w].push_back(v);
        ++m;
    }

    bool hasEdge(int v, int w) {
        assert(v >= 0 && v < n);
        assert(w >= 0 && w < n);
        for (int i = 0; i < g[v].size(); ++i) {
            if (g[v][i] == w)
                return true;
        }
        return false;
    }

    void Print() {
        for (int i = 0; i < g.size(); ++i) {
            cout << "边" << i << ":";
            for (int j = 0; j < g[i].size(); ++j) {
                cout << g[i][j] << " ";
            }
            cout << endl;
        }
    }

    void dfs(int v) {
        vector<bool> visited(n, false);
        stack<int> s;
        s.push(v);
        while (!s.empty()) {
            int tmp = s.top();
            if (!visited[tmp])
                cout << tmp << " ";
            visited[tmp] = true;
            s.pop();
            int size = g[tmp].size();
            for (int i = 0; i < size; ++i) {
                int b = g[tmp][i];
                if (!visited[b])
                    s.push(b);
            }
        }
        cout << endl;
    }

    void bfs(int v) {
        vector<bool> visited(n, false);
        queue<int> que;
        que.push(v);
        while (!que.empty()) {
            int tmp = que.front();
            if (!visited[tmp])
                cout << tmp << " ";
            visited[tmp] = true;
            que.pop();
            int size = g[tmp].size();
            for (int i = 0; i < size; ++i) {
                int b = g[tmp][i];
                if (!visited[b])
                    que.push(b);
            }
        }
        cout << endl;
    }
};

int main() {
    int vertex, edge;
    cin >> vertex >> edge;
    SparseGraph myGraph(vertex, false);
    for (int i = 0; i < edge; ++i) {
        int from, to;
        cin >> from >> to;
        assert(from >= 0 && from < vertex);
        assert(from >= 0 && from < vertex);
        myGraph.addEgde(from, to);
    }
    myGraph.Print();
    myGraph.dfs(0);
    myGraph.bfs(0);
    return 0;
}


 

2.邻接矩阵

邻接矩阵是表示顶点之间相邻关系的矩阵。他由V和E集合,其中,V是顶点,E是边。因此,用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。邻接矩阵又分有向图邻接矩阵和无向图邻接矩阵。

代码设计如下:

//
// Created by A on 2023/6/10.
//
#include <iostream>
#include <vector>
#include <cassert>
#include <stack>
#include <queue>

using namespace std;

class DenseGraph {
public:
    int n, m;
    bool directed;
    vector<vector<int> > g;


    DenseGraph(int n, bool directed) {
        this->n = n;
        this->m = m;
        this->directed = directed;
        for (int i = 0; i < n; ++i)
            g.push_back(vector<int>(n, 0));
    }

    ~DenseGraph() {

    }

    int V() {
        return n;
    }

    int E() {
        return m;
    }

    void addEgde(int v, int w) {
        assert(v >= 0 && v < n);
        assert(w >= 0 && w < n);
        if (hasEdge(v, w))
            return;
        g[v][w] = 1;
        if (!directed)
            g[w][v] = 1;
        ++m;
    }

    bool hasEdge(int v, int w) {
        assert(v >= 0 && v < n);
        assert(w >= 0 && w < n);
        return (g[v][w] == 1);
    }

    void Print() {
        for (int i = 0; i < g.size(); ++i) {
            for (int j = 0; j < g[i].size(); ++j) {
                cout << g[i][j] << " ";
            }
            cout << endl;
        }
    }

    void dfs(int v) {
        assert(v >= 0 && v < n);
        vector<bool> visited(n, false);
        stack<int> s;
        s.push(v);
        while (!s.empty()) {
            int tmp = s.top();
            if (!visited[tmp])
                cout << tmp << " ";
            visited[tmp] = true;
            s.pop();
            int size = g[tmp].size();
            for (int i = 0; i < size; ++i) {
                int b = g[tmp][i];
                if (b == 1 && !visited[i])
                    s.push(i);
            }
        }
        cout << endl;
    }

    void bfs(int v) {
        assert(v >= 0 && v < n);
        vector<bool> visited(n, false);
        queue<int> que;
        que.push(v);
        while (!que.empty()) {
            int tmp = que.front();
            if (!visited[tmp])
                cout << tmp << " ";
            visited[tmp] = true;
            que.pop();
            int size = g[tmp].size();
            for (int i = 0; i < size; ++i) {
                int b = g[tmp][i];
                if (b == 1 && !visited[i])
                    que.push(i);
            }
        }
        cout << endl;
    }

};

int main() {
    int vertex, edge;
    cin >> vertex >> edge;
    DenseGraph myGraph(vertex, false);
    for (int i = 0; i < edge; ++i) {
        int from, to;
        cin >> from >> to;
        assert(from >= 0 && from < vertex);
        assert(from >= 0 && from < vertex);
        myGraph.addEgde(from, to);
    }
    myGraph.Print();
    myGraph.dfs(0);
    myGraph.bfs(0);
    return 0;
}

3.深度优先遍历(DFS) 

图的深度优先遍历(Depth-First Search,DFS)是一种遍历图的方式,它从图的某个顶点开始,沿着一条路径一直走到底,直到不能继续为止,然后返回到上一个节点,继续尝试其他路径,直到所有的节点都被访问过为止。简单来说,就是尽可能深地访问每个节点,如果没有路可走就返回上一个节点。

具体实现时,可以使用递归或栈来实现深度优先遍历。在递归实现中,从起始节点开始,递归地遍历与该节点相邻的节点,直到遇到没有未被访问的相邻节点为止。在栈实现中,从起始节点开始,将其压入栈中,然后弹出栈顶节点,遍历该节点的未被访问的相邻节点,并将其压入栈中,直到栈为空为止。

4.图的广度优先遍历(BFS)

图的广度优先遍历(Breadth-First Search,BFS)是一种遍历图的方式,它从图的某个顶点开始,先访问该节点,然后访问与该节点相邻的所有节点,再依次访问这些相邻节点的相邻节点,直到所有节点都被访问过为止。简单来说,就是逐层访问节点,先访问距离起始节点最近的节点。

具体实现时,可以使用队列来实现广度优先遍历。从起始节点开始,将其加入队列,然后弹出队首节点,依次访问该节点的未被访问的相邻节点,并将其加入队列尾部,直到队列为空为止。需要注意的是,在访问每个节点时,要标记已经访问过的节点,以避免重复访问。

与深度优先遍历相比,广度优先遍历可以找到最短路径,因为它首先访问距离起始节点最近的节点。但是,广度优先遍历需要使用队列,空间复杂度比深度优先遍历高。

运行结果如下:

6 8
0 1
0 2
0 5
1 2
1 3
1 4
3 4
3 5
图的邻接表实现: 
边0:1 2 5 
边1:0 2 3 4 
边2:0 1 
边3:1 4 5 
边4:1 3 
边5:0 3 
深度优先遍历结果: 
0 5 3 4 1 2 
广度优先遍历结果: 
0 1 2 5 3 4 

6 8
0 1
0 2
0 5
1 2
1 3
1 4
3 4
3 5
图的邻接矩阵实现: 
0 1 1 0 0 1 
1 0 1 1 1 0 
1 1 0 0 0 0 
0 1 0 0 1 1 
0 1 0 1 0 0 
1 0 0 1 0 0 
深度优先遍历结果: 
0 5 3 4 1 2 
广度优先遍历结果: 
0 1 2 5 3 4 

  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你介绍一下邻接矩阵邻接表创建方法以及DFSBFS操作实现。 ## 邻接矩阵 邻接矩阵是一种创建的方式,它使用一个二维数组来表示中各个节点之间的关系。如果中有N个节点,那么邻接矩阵就是一个N*N的矩阵。其中,如果节点i和节点j之间有边相连,则邻接矩阵中第i行第j列的值为1,否则为0。 邻接矩阵创建方法如下: ```python # 创建邻接矩阵 def create_adj_matrix(graph, n): adj_matrix = [[0] * n for _ in range(n)] # 初始化邻接矩阵,全部为0 for i in range(n): for j in range(n): if graph[i][j] == 1: adj_matrix[i][j] = 1 return adj_matrix ``` 其中,graph是一个二维数组,表示原始的,n表示节点的个数。 接下来,我们可以使用DFSBFS算法遍历邻接矩阵表示的。 ## DFS DFS深度优先搜索)是一种递归的搜索算法,它从一个起始点开始,沿着一条路径一直到达最深处,直到无法继续下去时,返回上一个节点,然后选择另一条路径继续搜索,直到遍历完整个DFS实现方法如下: ```python # DFS遍历邻接矩阵 def dfs(adj_matrix, visited, n, start): visited[start] = True print(start, end=' ') for i in range(n): if adj_matrix[start][i] == 1 and not visited[i]: dfs(adj_matrix, visited, n, i) ``` 其中,adj_matrix是邻接矩阵,visited是一个数组,用于记录节点是否被访问过,n表示节点的个数,start表示起始节点。 ## BFS BFS(广度优先搜索)是一种非递归的搜索算法,它从一个起始点开始,先访问它的所有邻居节点,然后访问邻居节点的邻居节点,以此类推,直到遍历完整个BFS实现方法如下: ```python # BFS遍历邻接矩阵 def bfs(adj_matrix, visited, n, start): queue = [] visited[start] = True queue.append(start) while queue: node = queue.pop(0) print(node, end=' ') for i in range(n): if adj_matrix[node][i] == 1 and not visited[i]: visited[i] = True queue.append(i) ``` 其中,adj_matrix是邻接矩阵,visited是一个数组,用于记录节点是否被访问过,n表示节点的个数,start表示起始节点。queue是一个队列,用于存储待访问的节点。 ## 邻接表 邻接表是另一种创建的方式,它使用一个数组来表示中各个节点,每个节点对应一个链表,链表中存储该节点所连接的其他节点。 邻接表创建方法如下: ```python # 创建邻接表 def create_adj_list(graph, n): adj_list = [[] for _ in range(n)] # 初始化邻接表 for i in range(n): for j in range(n): if graph[i][j] == 1: adj_list[i].append(j) return adj_list ``` 其中,graph是一个二维数组,表示原始的,n表示节点的个数。 接下来,我们可以使用DFSBFS算法遍历邻接表表示的。 ## DFS DFS深度优先搜索)是一种递归的搜索算法,它从一个起始点开始,沿着一条路径一直到达最深处,直到无法继续下去时,返回上一个节点,然后选择另一条路径继续搜索,直到遍历完整个DFS实现方法如下: ```python # DFS遍历邻接表 def dfs(adj_list, visited, start): visited[start] = True print(start, end=' ') for i in adj_list[start]: if not visited[i]: dfs(adj_list, visited, i) ``` 其中,adj_list是邻接表,visited是一个数组,用于记录节点是否被访问过,start表示起始节点。 ## BFS BFS(广度优先搜索)是一种非递归的搜索算法,它从一个起始点开始,先访问它的所有邻居节点,然后访问邻居节点的邻居节点,以此类推,直到遍历完整个BFS实现方法如下: ```python # BFS遍历邻接表 def bfs(adj_list, visited, start): queue = [] visited[start] = True queue.append(start) while queue: node = queue.pop(0) print(node, end=' ') for i in adj_list[node]: if not visited[i]: visited[i] = True queue.append(i) ``` 其中,adj_list是邻接表,visited是一个数组,用于记录节点是否被访问过,start表示起始节点。queue是一个队列,用于存储待访问的节点。 希望这些代码可以帮助你更好地理解邻接矩阵邻接表创建方法以及DFSBFS算法实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值