图——邻接表和邻接矩阵——DFS、BFS算法

程序小白,希望和大家多交流,共同学习

//图,将实现图的两种存储,邻接表和邻接矩阵
//并实现图的创建,深度优先遍历(DFS),递归方法和非递归方法,广度优先遍历(BFS)
//两种存储方式,在使用深度优先遍历的使用上是一样的
#include<iostream>
#include<string>
#include<cstdio>
#include<stack>
#include<queue>
#define MAX_VN 50
#define INF 23767
using namespace std;
//邻接表
//使用的存储方式和二叉树的存储中的孩子表示法是相同的
//采用三层数据包装,弧结点,顶点结点,邻接表
//弧结点,表示临界点的关系
//顶点结点,记录结点信息,还有第一个临接点
//邻接表,确定邻接表中结点,结点个数和弧个数
typedef string VertexData;
struct ArcNode{
    int adjvex;
    int weight;
    ArcNode *nextArc;
};

struct VertexNode{
    VertexData data;
    ArcNode *firstArc;
};
struct AdjList{
    VertexNode vertex[MAX_VN];
    int verNum, arcNum;
};

//创建邻接表
void createAdjList(AdjList &G);
//根据给定的VertexData确定顶点的位置
int locateVertex(AdjList &G, VertexData data);
//输出邻接表
void outputAdjList(AdjList &G);
//递归方法进行深度优先遍历
//先访问给定的第一个顶点,然后访问此点的连接点,接着访问接下来点的临界点
//以此类推,一旦出现已经访问顶点,就返回上一个邻接点的下一个点,继续访问
void DFSdgAdjList(AdjList &G);
void DFSdgAdjList(AdjList &G, int v, bool *visited);
//得到指定顶点的第一个弧的adjvex
int firstAdjVertex(AdjList &G, int v);
//得到指定顶点和一条弧的下一个弧的adjvex
int nextAdjVertex(AdjList &G, int v, int m);
//访问输出邻接点信息
void visit(AdjList &G, int v);
//非递归深度优先遍历
void DFSfdgAdjList(AdjList &G);
void DFSfdgAdjList(AdjList &G, int v, bool *visited);
//广度优先遍历
void BFSAdjList(AdjList &G);
void BFSAdjList(AdjList &G, int v, bool *visited);

//临接矩阵
//使用连个数组,分别存储结点信息,和弧信息
//使用二维数组存储弧信息,行表示弧尾(起始),列表示弧头(结束)
struct AdjMatrix{
    VertexData vertex[MAX_VN];
    int arcs[MAX_VN][MAX_VN];
    int arcNum, verNum;
};
//创建临接矩阵
void createAdjMatrix(AdjMatrix &G);
//根据给定的VertexData确定顶点的位置
int locateVertex(AdjMatrix &G, VertexData data);
//输出邻接矩阵
void outputAdjMatrix(AdjMatrix &G);
//递归法进行深度优先遍历
void DFSdgAdjMatrix(AdjMatrix &G);
void DFSdgAdjMatrix(AdjMatrix &G, int v, bool *visited);
//得到指定顶点的第一个弧的adjvex
int firstAdjVertex(AdjMatrix &G, int v);
//得到指定顶点和一条弧的下一个弧的adjvex
int nextAdjVertex(AdjMatrix &G, int v, int m);
//访问输出邻接点信息
void visit(AdjMatrix &G, int v);
//非递归深度优先遍历
void DFSfdgAdjMatrix(AdjMatrix &G);
void DFSfdgAdjMatrix(AdjMatrix &G, int v, bool *visited);
//广度优先遍历
void BFSAdjMatrix(AdjMatrix &G);
void BFSAdjMatrix(AdjMatrix &G, int v, bool *visited);

int main(){
/*
6 10
v1 v2 v3 v4 v5 v6
v1 v2 5
v1 v4 7
v2 v3 4
v3 v1 8
v3 v6 9
v4 v3 5
v4 v6 6
v5 v4 5
v6 v1 2
v6 v5 1
*/
    AdjList GL;
    createAdjList(GL);
    outputAdjList(GL);
    cout << "DFSdgAdjList\n";
    DFSdgAdjList(GL);
    cout << endl;
    cout << "DFSfdgAdjList\n";
    DFSfdgAdjList(GL);
    cout << endl;
    cout << "BFSAdjList\n";
    BFSAdjList(GL);
    cout << endl;
    AdjMatrix GM;
    createAdjMatrix(GM);
    outputAdjMatrix(GM);
    cout << "DFSdgAdjMatrix\n";
    DFSdgAdjMatrix(GM);
    cout << endl;
    cout << "DFSfdgAdjMatrix\n";
    DFSfdgAdjMatrix(GM);
    cout << endl;
    cout << "BFSAdjMatrix\n";
    BFSAdjMatrix(GM);
    cout << endl;

    return 0;
}

//创建邻接表
void createAdjList(AdjList &G){
    cout << "输入临接表顶点个数和弧的条数:";
    cin >>G.verNum >> G.arcNum;
    cout << "输入各个顶点的信息:";
    for (int i = 1; i <= G.verNum; i++){
        cin >> G.vertex[i].data;
        G.vertex[i].firstArc = NULL;
    }
    cout << "输入各条弧的信息:";
    VertexData u, v;
    int w, j ,k;
    for (int i = 0; i < G.arcNum; i++){
        cin >> u >> v >> w;
        j = locateVertex(G, u);
        k = locateVertex(G, v);
        ArcNode *p = new ArcNode;
        p -> weight = w;
        p -> adjvex = k;
        p -> nextArc = G.vertex[j].firstArc;
        G.vertex[j].firstArc = p;
    }
}
//根据给定的VertexData确定顶点的位置
int locateVertex(AdjList &G, VertexData data){
    for (int i = 1; i <= G.verNum; i++){
        if (G.vertex[i].data == data){
            return i;
        }
    }
    return -1;
}
//输出邻接表
void outputAdjList(AdjList &G){
    for (int i = 1; i <= G.verNum; i++){
        cout << i << " " << G.vertex[i].data << " -> ";
        ArcNode *p = G.vertex[i].firstArc;
        while (p){
            cout << p -> adjvex <<" " << p -> weight << " -> ";
            p = p -> nextArc;
        }
        cout << " ^" << endl;
    }
    cout << endl;
}
//递归方法进行深度优先遍历
void DFSdgAdjList(AdjList &G){
    bool *visited = new bool[G.verNum + 1];
    for (int i = 1; i <= G.verNum; i++){
        visited[i] = false;
    }
    for (int i = 1; i <= G.verNum; i++){
        if (!visited[i]){
            DFSdgAdjList(G, i, visited);
        }
    }
}
void DFSdgAdjList(AdjList &G, int v, bool *visited){
    visit(G, v);
    visited[v] = true;
    int n = firstAdjVertex(G, v);
    while (n != -1){
        if (!visited[n]){
            DFSdgAdjList(G, n, visited);
        }
        n = nextAdjVertex(G, v, n);
    }
}
//得到指定顶点的第一个弧的adjvex
int firstAdjVertex(AdjList &G, int v){
    ArcNode *p = G.vertex[v].firstArc;
    if (p){
        return p -> adjvex;
    }
    return -1;
}
//得到指定顶点和一条弧的下一个弧的adjvex
int nextAdjVertex(AdjList &G, int v, int m){
    ArcNode *p = G.vertex[v].firstArc;
    while (p && p -> adjvex != m){
        p = p -> nextArc;
    }
    if (p && p -> nextArc){
        return p -> nextArc -> adjvex;
    }
    return -1;
}
//访问输出邻接点信息
void visit(AdjList &G, int v){
    cout << G.vertex[v].data << " ";
}
//非递归深度优先遍历
void DFSfdgAdjList(AdjList &G){
    bool *visited = new bool[G.verNum + 1];
    for (int i = 1; i <= G.verNum; i++){
        visited[i] = false;
    }
    for (int i = 1; i <= G.verNum; i++){
        if (!visited[i]){
            DFSfdgAdjList(G, i, visited);
        }
    }
}
void DFSfdgAdjList(AdjList &G, int v, bool *visited){
    stack<int> s;
    s.push(v);
    while (!s.empty()){
        int w = s.top();
        s.pop();
        if (!visited[w]){
            visit(G, w);
            visited[w] = true;
        }
        int u = firstAdjVertex(G, w);
        while (u != -1){
            if (!visited[u]){//邻接点对应的顶点只要没有被访问就入栈
                s.push(u);
            }
            u = nextAdjVertex(G, v, u);
        }
    }
}
//广度优先遍历
void BFSAdjList(AdjList &G){
    bool *visited = new bool[G.verNum + 1];
    for (int i = 1; i <= G.verNum; i++){
        visited[i] = false;
    }
    for (int i = 1; i <= G.verNum; i++){
        if (!visited[i]){
            BFSAdjList(G, i, visited);
        }
    }
}
void BFSAdjList(AdjList &G, int v, bool *visited){
    queue<int> q;
    q.push(v);
    while (!q.empty()){
        int w = q.front();
        q.pop();
        if (!visited[w]){
            visit(G, w);
            visited[w] = true;
        }

        int n = firstAdjVertex(G, v);
        while (n != -1){
            if (!visited[n]){
                q.push(n);
            }
            n = nextAdjVertex(G, v, n);
        }
    }
}



//创建临接矩阵
void createAdjMatrix(AdjMatrix &G){
    cout << "输入邻接矩阵顶点的个数和弧的条数:";
    cin >> G.verNum >> G.arcNum;
    cout << "输入顶点信息:";
    for (int i = 0; i < G.verNum; i++){
        cin >> G.vertex[i];
    }

    for (int i = 0; i< G.verNum; i++){
        for (int j = 0; j < G.verNum; j++){
            G.arcs[i][j] = INF;
        }
    }
    cout << "输入弧的信息:";
    VertexData u, v;
    int w, j, k;
    for (int i = 0; i < G.arcNum; i++){
        cin >> u >> v >> w;
        j = locateVertex(G, u);
        k = locateVertex(G, v);
        G.arcs[j][k] = w;
    }
}
//根据给定的VertexData确定顶点的位置
int locateVertex(AdjMatrix &G, VertexData data){
    for (int i = 0; i < G.verNum; i++){
        if (G.vertex[i] == data){
            return i;
        }
    }
    return -1;
}
//输出邻接矩阵
void outputAdjMatrix(AdjMatrix &G){
    for (int i = 0; i < G.verNum; i++){
        for (int j = 0; j < G.verNum; j++){
            if (G.arcs[i][j] == INF){
                cout << "∞  ";
            }
            else
                printf("%-4d", G.arcs[i][j]);
        }
        cout << endl;
    }
}
//递归法进行深度优先遍历
void DFSdgAdjMatrix(AdjMatrix &G){
    bool *visited = new bool[G.verNum];
    for (int i = 0; i < G.verNum; i++){
        visited[i] = false;
    }
    for (int i = 0; i < G.verNum; i++){
        if (!visited[i]){
            DFSdgAdjMatrix(G, i, visited);
        }
    }
}
void DFSdgAdjMatrix(AdjMatrix &G, int v, bool *visited){
    visit(G, v);
    visited[v] = true;
    int n = firstAdjVertex(G, v);
    while (n != -1){
        if (!visited[n]){
            DFSdgAdjMatrix(G, n, visited);
        }
        n = nextAdjVertex(G, v, n);
    }
}
//得到指定顶点的第一个弧的adjvex
int firstAdjVertex(AdjMatrix &G, int v){
    for (int i = 0; i < G.verNum; i++){
        if (G.arcs[v][i] != INF){
            return i;
        }
    }
    return -1;
}
//得到指定顶点和一条弧的下一个弧的adjvex
int nextAdjVertex(AdjMatrix &G, int v, int m){
    for (int i = m + 1; i < G.verNum; i++){
        if (G.arcs[v][i] != INF){
            return i;
        }
    }
    return -1;
}
//访问输出邻接点信息
void visit(AdjMatrix &G, int v){
    cout << G.vertex[v] << " ";
}
//非递归深度优先遍历
void DFSfdgAdjMatrix(AdjMatrix &G){
    bool *visited = new bool[G.verNum];
    for (int i = 0; i < G.verNum; i++){
        visited[i] = false;
    }
    for (int i = 0; i < G.verNum; i++){
        if (!visited[i]){
            DFSfdgAdjMatrix(G, i, visited);
        }
    }
}
void DFSfdgAdjMatrix(AdjMatrix &G, int v, bool *visited){
    stack<int> s;
    s.push(v);
    while (!s.empty()){
        int w = s.top();
        s.pop();
        if (!visited[w]){
            visit(G, w);
            visited[w] = true;
        }
        int n = nextAdjVertex(G, v, w);
        while (n != -1){
            if (!visited[n]){
                s.push(n);
            }
            n = nextAdjVertex(G, v, n);
        }
    }
}
//广度优先遍历
void BFSAdjMatrix(AdjMatrix &G){
    bool *visited = new bool[G.verNum];
    for (int i = 0; i < G.verNum; i++){
        visited[i] = false;
    }
    for (int i = 0; i < G.verNum; i++){
        if (!visited[i]){
            BFSAdjMatrix(G, i, visited);
        }
    }
}
void BFSAdjMatrix(AdjMatrix &G, int v, bool *visited){
    queue<int> q;
    q.push(v);
    while (!q.empty()){
        int w = q.front();
        q.pop();
        if (!visited[w]){
            visit(G, w);
            visited[w] = true;
        }
        int f = firstAdjVertex(G, v);
        while (f != -1){
            if (!visited[f]){
                q.push(f);
            }
            f = nextAdjVertex(G, v, f);
        }
    }
}
/*
输入临接表顶点个数和弧的条数:6 10
输入各个顶点的信息:v1 v2 v3 v4 v5 v6
输入各条弧的信息:v1 v2 5
v1 v4 7
v2 v3 4
v3 v1 8
v3 v6 9
v4 v3 5
v4 v6 6
v5 v4 5
v6 v1 2
v6 v5 1
1 v1 -> 4 7 -> 2 5 ->  ^
2 v2 -> 3 4 ->  ^
3 v3 -> 6 9 -> 1 8 ->  ^
4 v4 -> 6 6 -> 3 5 ->  ^
5 v5 -> 4 5 ->  ^
6 v6 -> 5 1 -> 1 2 ->  ^

DFSdgAdjList
v1 v4 v6 v5 v3 v2
DFSfdgAdjList
v1 v2 v3 v6 v5 v4
BFSAdjList
v1 v4 v2 v3 v6 v5
输入邻接矩阵顶点的个数和弧的条数:6 10
输入顶点信息:v1 v2 v3 v4 v5 v6
输入弧的信息:v1 v2 5
v1 v4 7
v2 v3 4
v3 v1 8
v3 v6 9
v4 v3 5
v4 v6 6
v5 v4 5
v6 v1 2
v6 v5 1
∞  5   ∞  7   ∞  ∞
∞  ∞  4   ∞  ∞  ∞
8   ∞  ∞  ∞  ∞  9
∞  ∞  5   ∞  ∞  6
∞  ∞  ∞  5   ∞  ∞
2   ∞  ∞  ∞  1   ∞
DFSdgAdjMatrix
v1 v2 v3 v6 v5 v4
DFSfdgAdjMatrix
v1 v4 v2 v3 v6 v5
BFSAdjMatrix
v1 v2 v4 v3 v6 v5
*/

猜你喜欢

转载自blog.csdn.net/cheng_cuo_tuo/article/details/80516008