图的遍历(dfs、bfs、最短路、最小生成树、拓扑排序)

代码如下:

#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
#define MAXSIZE 100
bool vis[MAXSIZE+5];
int in[MAXSIZE+11];		//入度 
int f[MAXSIZE+11];		//并查集指向根节点 
typedef struct
{
    int x,y;
    int cost;
}road[(MAXSIZE*MAXSIZE+MAXSIZE)>>1],Road;

typedef struct		//邻接矩阵 
{
    int arcs[MAXSIZE+5][MAXSIZE+5];
    int vexnum,arcnum;
    void init()
    {
        CLR(this->arcs,0);
        this->arcnum = this->vexnum = 0;
    }
}AMGraph;

typedef struct ArcNode		//邻接表,顶点序号用数字表示 
{
    int adjvex;
    struct ArcNode *nextarc;
}AdjList[MAXSIZE+5],AdjNode;
typedef struct
{
    AdjList vectices;
    int vexnum,arcnum;		//顶点、边数 
    void init()		//初始化 
    {
        for (int i = 1 ; i <= MAXSIZE ; i++)
            this->vectices[i].nextarc = NULL;
        this->arcnum = this->vexnum = 0;
    }
    void Insert(int pos,AdjNode &t)		//在pos点后连接t节点
    {
        t.nextarc = this->vectices[pos].nextarc;
        this->vectices[pos].nextarc = &t;
    }
}ALGraph;

typedef struct Queue		//队列 
{
    int data;
    struct Queue *next;
    struct Queue *end;		//队列末节点 
    void init()
    {
        this->end = this;
        this->next = NULL;
    }
    int GetTop()
    {
        return this->next->data;
    }
    bool Empty()
    {
        if (this->next == NULL)
            return true;
        return false;
    }
    void Pop()
    {
        Queue *t = this->next;
        this->next = this->next->next;
        free(t);
        if (this->Empty())		//如果队列为空,队尾指针指向自己 
            this->end = this;
    }
    void Push(int x)
    {
        Queue *t;
        t = (Queue *)malloc(sizeof(Queue));
        t->data = x;
        t->next = NULL;
        this->end->next = t;
        this->end = t;
    }
}Queue;

void dfsSearch(AMGraph &mm,int pos)		//递归求DFS 
{
    printf ("%d ",pos);
    vis[pos] = true;
    for (int i = 1 ; i <= mm.vexnum ; i++)
    {
        if (!vis[i] && mm.arcs[pos][i])
            dfsSearch(mm,i);
    }
}
void DFS(AMGraph &mm)
{
    printf ("该无向图的DFS序为:");
    dfsSearch(mm,1);
    puts("");
}

void BFS(AMGraph &mm)
{
    printf ("该无向图的BFS序为:");
    CLR(vis,false);
    Queue q;
    q.init();
    q.Push(1);
    vis[1] = true;
    while (!q.Empty())
    {
        int pr = q.GetTop();
        q.Pop();
        printf ("%d ",pr);
        for (int i = 1 ; i <= mm.vexnum ; i++)
        {
            if (!vis[i] && mm.arcs[pr][i])		//没有遍历过,并且存在边 
            {
                q.Push(i);
                vis[i] = true;
            }
        }
    }
    printf ("\n"); 
}

void dijkstra(AMGraph &mm)
{
    CLR(vis,false);
    int dis[MAXSIZE+5];
    CLR(dis,INF);
    dis[1] = 0;
    while (1)
    {
        int v = -1;
        for (int i = 1 ; i <= mm.vexnum ; i++)
        {
            if (!vis[i] && (v == -1 || dis[i] < dis[v]))
                v = i;
        }
        if (v == -1)
            break;
        vis[v] = true;		//标记 
        for (int i = 1 ; i <= mm.vexnum ; i++)
        {
            if (vis[i] == false && mm.arcs[v][i])
                dis[i] = min(dis[i] , dis[v] + mm.arcs[v][i]);
        }
    }
    printf ("%d\n",dis[mm.vexnum] == INF ? -1 : dis[mm.vexnum]);		//不存在最短路径输入-1 
}
void ShortestRoad(AMGraph &mm)
{
    printf ("从1点到%d点的最短路径为(不存在输出-1):",mm.vexnum);
    dijkstra(mm);
}

int find(int x)		//递归寻根节点并路径压缩 
{
    if (x != f[x])
        f[x] = find(f[x]);
    return f[x];
}
bool join(int x,int y)		//合并节点
{
    int fx,fy;
    fx = find(x);
    fy = find(y);
    if (fx != fy)
    {
        f[fx] = fy;
        return true;
    }
    return false;
}
bool cmp(Road a,Road b)
{
    return a.cost < b.cost;
}
void Kruskal(AMGraph &mm)
{
    for (int i = 1 ; i <= mm.vexnum ; i++)
        f[i] = i;		//初始化并查集根节点 
    int ant = 0;
    road d;
    for (int i = 1 ; i < mm.vexnum ; i++)
    {
        for (int j = i + 1 ; j <= mm.vexnum ; j++)
        {
            if (mm.arcs[i][j])
            {
                d[ant].x = i;
                d[ant].y = j;
                d[ant++].cost = mm.arcs[i][j];
            }
        }
    }
    sort(d,d+ant,cmp);
    int cost = 0;		//最小花费 
    for (int i = 0 ; i < ant ; i++)
    {
        if (join(d[i].x , d[i].y))
            cost += d[i].cost;
    }
    printf ("%d\n",cost);
}
void MiniSpanTree(AMGraph &mm)
{
    printf ("最小生成树的最小花费为:");
    Kruskal(mm);
}

void Topo(ALGraph &am)
{
    printf ("拓扑排序结果为:");
    Queue q;
    q.init();
    for (int i = 1 ; i <= am.vexnum ; i++)
    {
        if (!in[i])
            q.Push(i);
    }
    while (!q.Empty())
    {
        int pr = q.GetTop();
        printf ("%d ",pr);
        q.Pop();
        in[pr] = -1;
        AdjNode *t;
        t = am.vectices[pr].nextarc;
        while (t != NULL)
        {
            in[t->adjvex]--;
            if (!in[t->adjvex])
                q.Push(t->adjvex);
            t = t->nextarc;
        }
    }
    puts("");
}

int main()
{
    int arcnum,vexnum;
    AMGraph mm;		//Matrix map
    ALGraph am;		//Adj map
    mm.init() , am.init();
    printf ("请输入顶点数的边数:");
    scanf ("%d %d",&vexnum,&arcnum);
    am.arcnum = mm.arcnum = arcnum;
    am.vexnum = mm.vexnum = vexnum;
    printf ("请输入%d条边(DFS、BFS、最短路、最小生成树中存为无向图 ; 拓扑排序用有向图):\n",arcnum);
    for (int i = 1 ; i <= arcnum ; i++)		//读入数据 
    {
        int x,y,z;		//顶点,边的权值
        scanf ("%d %d %d",&x,&y,&z);
        mm.arcs[x][y] = mm.arcs[y][x] = z;
        AdjNode t;
        t.adjvex = y;
        t.nextarc = NULL;
        in[y]++;
        am.Insert(x,t);		//插入邻接表中 
    }
    DFS(mm);
    BFS(mm);
    ShortestRoad(mm);
    MiniSpanTree(mm);
    Topo(am);
    return 0;
}

/*
1 3 1
3 7 1
7 6 1
6 3 1
1 2 1
2 5 1
5 8 1
8 4 1
4 2 1
*/

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/wyg1997/article/details/53056917
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞