图的深度、广度优先遍历算法(含无向图、有向图的构造)


算法逻辑可能并不严谨,欢迎各位大佬批评指正!


一、非递归实现深度优先遍历

1、算法思想

(1)算法思想:

  • 首先检查起始顶点的索引是否有效和图是否已经建立。
  • 使用栈来实现深度优先搜索,首先将起始顶点入栈,并将起始顶点标记为已访问。
  • 循环直到栈为空,每次取出栈顶顶点,打印并访问它的邻接顶点,并将未访问的邻接顶点入栈并标记为已访问。

(2)时间复杂度: O(V + E)
(3)空间复杂度: O(V),其中V是顶点数,E是边数。

2、算法流程图

在这里插入图片描述

3、算法

//深度优先
void DFS(int start) {
    if (start < 0 || start >= numVertices) {
        cout << "起始顶点不在图形中" << endl;
        return;
    }

    if (checkGraphBuilt()) {
        vector<bool> visited(numVertices, false);
        stack<int> s;
        s.push(start);
        visited[start] = true;

        while (!s.empty()) {
            int current = s.top();
            s.pop();

            if (current < 0 || current >= numVertices) {
                continue;
            }

            printNode(current);

            for (auto node : adjList[current]) {
                if (!visited[node.dest]) {
                    s.push(node.dest);
                    visited[node.dest] = true;
                }
            }
        }
        cout << endl;
    }
}

二、广度优先遍历

1、算法思想

(1)算法思想:

  • 首先检查起始顶点的索引是否有效和图是否已经建立。
  • 使用队列来实现广度优先搜索,首先将起始顶点入队,并将起始顶点标记为已访问。
  • 循环直到队列为空,每次取出队首顶点,打印并访问它的邻接顶点,并将未访问的邻接顶点入队并标记为已访问。

(2)时间复杂度: O(V + E)
(3)空间复杂度: O(V),其中V是顶点数,E是边数。

2、算法流程图

在这里插入图片描述

3、算法

//广度优先
void BFS(int start) {
    if (start < 0 || start >= numVertices) {
        cout << "起始顶点不在图形中" << endl;
        return;
    }

    if (checkGraphBuilt()) {
        vector<bool> visited(numVertices, false);
        queue<int> q;
        q.push(start);
        visited[start] = true;

        while (!q.empty()) {
            int current = q.front();
            q.pop();

            if (current < 0 || current >= numVertices) {
                continue;
            }

            printNode(current);

            for (auto node : adjList[current]) {
                if (!visited[node.dest]) {
                    q.push(node.dest);
                    visited[node.dest] = true;
                }
            }
        }
        cout << endl;
    }
}

三、附检测算法完整程序(含无向图、有向图的构造)

1、操作说明

  1. 根据菜单指示输入要进行的操作相应的数字

  2. 输入数字1将会输出已经构造好的无向网。

  3. 输入数字2将进入键盘输入有向图的操作,输入顶点个数(规定顶点是从0开始的数字,如:顶点个数为4,则顶点分别是0、1、2、3),输入边的起点和终点。
    在这里插入图片描述

  4. 输入数字3输出有向图

  5. 输入数字4输出无向图深度优先非递归遍历结果

  6. 输入数字5输出无向图广度优先遍历结果

  7. 输入数字6退出程序

2、测试结果图

  • 构建无向网

在这里插入图片描述

  • 构建有向图、输出邻接表

在这里插入图片描述

  • 深度优先非递归遍历、广度优先遍

在这里插入图片描述

3、完整代码

#include <iostream>
#include <vector>
#include <queue>
#include <stack>

using namespace std;

class Graph {
private:
    struct Node {
        int dest;
        Node(int d) : dest(d) {}
    };

    int numVertices;
    vector<vector<int>> adjMatrix;
    vector<vector<Node>> adjList;
    vector<vector<Node>> adjGraph;
    bool isDirected;
    bool isGraphBuilt;
public:
    Graph() : numVertices(0), isDirected(false), isGraphBuilt(false) {}
    //初始化图
    void initializeGraph(int n, bool directed) {
        numVertices = n;
        isDirected = directed;
        adjMatrix = vector<vector<int>>(numVertices, vector<int>(numVertices, 0));
        adjList = vector<vector<Node>>(numVertices);
        adjGraph = vector<vector<Node>>(numVertices);
        isGraphBuilt = true;
    }

    //将边添加到邻接矩阵中
    void addEdgeToMatrix(int src, int dest, int weight) {
        if (checkGraphBuilt() && checkVertexIndex(src) && checkVertexIndex(dest)) {
            if (src <= numVertices && dest <= numVertices) {
                adjMatrix[src][dest] = weight;
                if (!isDirected) {
                    adjMatrix[dest][src] = weight;
                }
            }
            else {
                cout << "顶点索引越界!" << endl;
            }
        }
    }

    //将边添加到邻接表中
    void addEdgeToAdjList(int src, int dest) {
        if (checkGraphBuilt() && checkVertexIndex(src) && checkVertexIndex(dest)) {
            if (src <= numVertices && dest <= numVertices) {
                if (!isDirected) {
                    adjList[src].push_back(Node(dest));
                    adjList[dest].push_back(Node(src));
                }
                else {
                    adjGraph[src].push_back(Node(dest));
                }
            }
            else {
                cout << "顶点索引越界!" << endl;
            }
            
        }
    }
    
    //打印无向网
    void printAdjMatrix() {
        if (checkGraphBuilt()) {
            cout << "无向网邻接矩阵表示:" << endl;
            for (int i = 0; i < numVertices; i++) {
                for (int j = 0; j < numVertices; j++) {
                    if (i < numVertices && j < numVertices) {
                        cout << adjMatrix[i][j] << " ";
                    }
                    else {
                        cout << "顶点索引越界!";
                    }
                }
                cout << endl;
            }
        }
    }
    //键盘输入有向图
    void buildAdjListFromInput() {
        if (checkGraphBuilt()) {
            int src, dest;
            cout << "请输入边的起点和终点 (格式: 起点 终点),输入-1 -1结束输入:" << endl;
            while (true) {
                cin >> src >> dest;
                if (src == -1 && dest == -1) {
                    break;
                }
                if (checkVertexIndex(src) && checkVertexIndex(dest) && src <= numVertices && dest <= numVertices) {
                    addEdgeToAdjList(src, dest);
                }
                else {
                    cout << "无效的顶点索引!请重新输入:" << endl;
                }
            }
        }
    }

    //打印有向图的邻接表
    void printAdjList() {
        if (checkGraphBuilt()) {
            for (int i = 0; i < numVertices; ++i) {
                if (checkVertexIndex(i)) {
                    cout << "顶点 " << i << " 的邻接表: ";
                    for (auto node : adjGraph[i]) {
                        if (checkVertexIndex(node.dest)) {
                            printNode(node.dest);
                        }
                        else {
                            cout << "无效的顶点索引:" << node.dest;
                        }
                    }
                    cout << endl;
                }
                else {
                    cout << "无效的顶点索引:" << i << endl;
                }
            }
        }
    }

    //深度优先
    void DFS(int start) {
        if (start < 0 || start >= numVertices) {
            cout << "起始顶点不在图形中" << endl;
            return;
        }

        if (checkGraphBuilt()) {
            vector<bool> visited(numVertices, false);
            stack<int> s;
            s.push(start);
            visited[start] = true;

            while (!s.empty()) {
                int current = s.top();
                s.pop();

                if (current < 0 || current >= numVertices) {
                    continue;
                }

                printNode(current);

                for (auto node : adjList[current]) {
                    if (!visited[node.dest]) {
                        s.push(node.dest);
                        visited[node.dest] = true;
                    }
                }
            }
            cout << endl;
        }
    }

    //广度优先
    void BFS(int start) {
        if (start < 0 || start >= numVertices) {
            cout << "起始顶点不在图形中" << endl;
            return;
        }

        if (checkGraphBuilt()) {
            vector<bool> visited(numVertices, false);
            queue<int> q;
            q.push(start);
            visited[start] = true;

            while (!q.empty()) {
                int current = q.front();
                q.pop();

                if (current < 0 || current >= numVertices) {
                    continue;
                }

                printNode(current);

                for (auto node : adjList[current]) {
                    if (!visited[node.dest]) {
                        q.push(node.dest);
                        visited[node.dest] = true;
                    }
                }
            }
            cout << endl;
        }
    }
private:
    bool checkGraphBuilt() {
        if (!isGraphBuilt) {
            cout << "未建立图!" << endl;
            return false;
        }
        return true;
    }

    bool checkVertexIndex(int index) {
        if (index < 0 || index >= numVertices) {
            cout << "无效的顶点索引!" << endl;
            return false;
        }
        return true;
    }

    void printNode(int node) {
        cout << "-> " << node;
    }
};
int main() {
    Graph graph;
    int choice;
    int numVertices = 0;
    bool isDirected = false;

    while (1) {
        cout << "--------菜单--------" << endl;
        cout << "1. 构造无向网" << endl;
        cout << "2. 键盘输入有向图" << endl;
        cout << "3. 输出邻接表" << endl;
        cout << "4. 无向图的深度优先非递归遍历" << endl;
        cout << "5. 无向图的广度优先遍历" << endl;
        cout << "6. 退出程序" << endl;
        cout << "请输入选项:";
        cin >> choice;

        switch (choice) {
        case 1:
            numVertices = 4;
            isDirected = false;
            graph.initializeGraph(numVertices, isDirected);
            graph.addEdgeToMatrix(0, 1, 1);
            graph.addEdgeToMatrix(0, 2, 2);
            graph.addEdgeToMatrix(1, 2, 3);
            graph.addEdgeToMatrix(2, 3, 4);
            graph.printAdjMatrix();
            break;
        case 2:
            cout << "请输入顶点个数(规定顶点是从0开始的数字,如:顶点个数为4,则顶点分别是0、1、2、3): ";
            cin >> numVertices;
            isDirected = true;
            graph.initializeGraph(numVertices, isDirected);
            graph.buildAdjListFromInput();
            break;
        case 3:
            graph.printAdjList();
            break;
        case 4:
            numVertices = 4;
            isDirected = false;
            graph.initializeGraph(numVertices, isDirected);
            graph.addEdgeToAdjList(0, 1);
            graph.addEdgeToAdjList(0, 2);
            graph.addEdgeToAdjList(1, 2);
            graph.addEdgeToAdjList(2, 3);
            cout << "深度优先非递归遍历结果:" << endl;
            graph.DFS(0);
            break;
        case 5:
            numVertices = 4;
            isDirected = false;
            graph.initializeGraph(numVertices, isDirected);
            graph.addEdgeToAdjList(0, 1);
            graph.addEdgeToAdjList(0, 2);
            graph.addEdgeToAdjList(1, 2);
            graph.addEdgeToAdjList(2, 3);
            cout << "广度优先遍历结果:" << endl;
            graph.BFS(0);
            break;
        case 6:
            return 0;
        default:
            cout << "无效的选项!" << endl;
            break;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值