• 数据结构之邻接矩阵(C++版)


    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    #define INFINITY 1000 //最大值∞
    #define MAX_VERTEX_NUM 20 //最大顶点个数
    #define MAXLISTSIZE 100 //循环队列的最大容量
    #define TRUE 1
    #define FALSE 0
    using namespace std;
    typedef enum{DG, DN, AG, AN}GraphKind; //类型标志{有向图,有向网,无向图,无向网}
    typedef int VRType;
    typedef char VertexType;
    typedef int ElemType;

    bool visited[MAX_VERTEX_NUM]; //全局变量,访问标志数组

    typedef struct ArcCell
    { //弧的定义
    VRType adj; //VRType是顶点关系类型。对无权图,用1或0表示相邻否;对带权图,则为权值类型。
    }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    typedef struct{ //图的定义
    VertexType vexs[MAX_VERTEX_NUM]; //顶点信息
    AdjMatrix arcs; //表示顶点之间关系的二维数组
    int vexnum, arcnum; //图的当前顶点数和弧(边)数
    int kind; //图的种类标志
    }MGraph;

    typedef struct
    {
    ElemType *elem; //存储空间基址   
    int rear; //队尾指针   
    int front; //队头指针
    int queuesize; //允许的最大存储空间,以元素为单位  
    }Queue;

    void InitQueue(Queue &Q, int maxsize)
    {
    //构造一个最大存储空间为 maxsize 的空队列 Q  
    if (maxsize == 0)
    maxsize = MAXLISTSIZE;
    Q.elem = new ElemType[maxsize]; //为循环队列分配存储空间  
    if (!Q.elem) exit(1); //存储分配失败
    Q.queuesize = maxsize;
    Q.front = Q.rear = 0;
    } //InitQueue

    bool EnQueue(Queue &Q, ElemType e)
    {
    // 若当前队列不满,这在当前队列的尾元素之后,插入元素 e 为新的队列尾元素,并返回TRUE,否则返回FALSE
    if((Q.rear + 1) % Q.queuesize == Q.front)
    return FALSE;
    Q.elem[Q.rear] = e;
    Q.rear = (Q.rear+1) % Q.queuesize;
    return TRUE;
    }

    bool DeQueue(Queue &Q, ElemType &e)
    {
    //若队列不空,则删除当前队列Q中的头元素,用 e 返回其值,并返回TRUE,否则返回 FALSE 
    if (Q.front == Q.rear)
    return FALSE;
    e = Q.elem[Q.front];
    Q.front = (Q.front+1) % Q.queuesize;
    return TRUE;
    }

    bool QueueEmpty(Queue Q)
    {
    if(Q.front == Q.rear)
    return TRUE;
    else
    return FALSE;
    }

    void DestroyQueue(Queue &Q)
    {
    delete[] Q.elem;
    Q.queuesize = 0;
    }

    int LocateVex(MGraph G, VertexType v)
    { //初始条件:图G存在,v和G中顶点有相同特征
    //操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
    int i;
    for(i = 0; i < G.vexnum; ++i)
    if(v == G.vexs[i])
    return i;
    return -1;
    }

    void CreateDG(MGraph &G)
    { //采用数组(邻接矩阵)表示法,构造有向图G。
    int i, j, k;
    VertexType va, vb; //顶点
    cout << "请输入邻接矩阵的顶点数和边数:";
    cin >> G.vexnum >> G.arcnum;
    cout << "请输入邻接矩阵的顶点:";
    for(i = 0; i < G.vexnum; ++i) //构造顶点向量
    cin >> G.vexs[i];
    for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
    for(j = 0; j < G.vexnum; ++j)
    {
    G.arcs[i][j].adj = 0; //有向网,初始化为0
    }
    for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
    {
    cout << "请输入第" << k + 1 << "条弧的起点(行)和终点(列): ";
    cin >> va >> vb; //输入一条边依附的顶点
    i = LocateVex(G, va);
    j = LocateVex(G, vb); //确定va和vb在G中的位置
    G.arcs[i][j].adj = 1; //顶点间有边赋值为1
    }//for
    }//CreateDG

    void CreateDN(MGraph &G)
    { //采用数组(邻接矩阵)表示法,构造有向网G。
    int i, j, k;
    VRType w; //权值
    VertexType va, vb; //顶点
    cout << "请输入邻接矩阵的顶点数和边数:";
    cin >> G.vexnum >> G.arcnum;
    cout << "请输入邻接矩阵的顶点:";
    for(i = 0; i < G.vexnum; ++i) //构造顶点向量
    cin >> G.vexs[i];
    for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
    for(j = 0; j < G.vexnum; ++j)
    {
    G.arcs[i][j].adj = INFINITY; //有向网,初始化为最大值
    }
    for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
    {
    cout << "请输入第" << k + 1 << "条弧的起点(行)和终点(列)和权值: ";
    cin >> va >> vb >> w; //输入一条边依附的顶点及权值
    i = LocateVex(G, va);
    j = LocateVex(G, vb); //确定va和vb在G中的位置
    G.arcs[i][j].adj = w; //w为权值
    }//for
    }//CreateDN

    void CreateAG(MGraph &G)
    { //采用数组(邻接矩阵)表示法,构造无向图G。
    int i, j, k;
    VertexType va, vb; //顶点
    cout << "请输入邻接矩阵的顶点数和边数:";
    cin >> G.vexnum >> G.arcnum;
    cout << "请输入邻接矩阵的顶点:";
    for(i = 0; i < G.vexnum; ++i) //构造顶点向量
    cin >> G.vexs[i];
    for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
    for(j = 0; j < G.vexnum; ++j)
    {
    G.arcs[i][j].adj = 0; //无向图,初始化为0
    }
    for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
    {
    cout << "请输入第" << k + 1 << "条弧的两顶点: ";
    cin >> va >> vb; //输入一条边依附的顶点
    i = LocateVex(G, va);
    j = LocateVex(G, vb); //确定va和vb在G中的位置
    G.arcs[i][j].adj = 1; //顶点间有边赋值为1
    G.arcs[j][i] = G.arcs[i][j];
    }//for
    }//CreateAG

    void CreateAN(MGraph &G)
    { //采用数组(邻接矩阵)表示法,构造无向网G。
    int i, j, k;
    VRType w; //权值
    VertexType va, vb; //顶点
    cout << "请输入邻接矩阵的顶点数和边数:";
    cin >> G.vexnum >> G.arcnum;
    cout << "请输入邻接矩阵的顶点:";
    for(i = 0; i < G.vexnum; ++i) //构造顶点向量
    cin >> G.vexs[i];
    for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
    for(j = 0; j < G.vexnum; ++j)
    {
    G.arcs[i][j].adj = INFINITY; //无向网,初始化为最大值
    }
    for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
    {
    cout << "请输入第" << k + 1 << "条弧的两顶点和权值: ";
    cin >> va >> vb >> w; //输入一条边依附的顶点及权值
    i = LocateVex(G, va);
    j = LocateVex(G, vb); //确定va和vb在G中的位置
    G.arcs[i][j].adj = w; //w为权值
    G.arcs[j][i] = G.arcs[i][j];
    }//for
    }//CreateAN


    void CreateGraph(MGraph &G)
    { //采用数组(邻接矩阵)表示法,构造图G。
    cout << "请输入图的类型(输入前面的数字){0.有向图, 1.有向网, 2.无向图, 3.无向网}:" << endl;
    cin >> G.kind;
    switch(G.kind)
    {
    case DG:
    CreateDG(G); //构造有向图
    break;
    case DN:
    CreateDN(G); //构造有向网
    break;
    case AG:
    CreateAG(G); //构造无向图
    break;
    case AN:
    CreateAN(G); //构造无向网
    break;
    default:
    cout <<"输入的图的类型错误:" << endl;
    break;
    }
    return;
    }

    int FirstAdjVex(MGraph G, int v)
    {
    int j, k = -1;
    for(j = 0; j < G.vexnum; j++)
    if(G.arcs[v][j].adj==1)
    {
    k = j;
    break;
    }
    return k;
    }

    int NextAdjVex(MGraph G, int v, int w)
    {
    int j, k = -1;
    for(j = w + 1; j < G.vexnum; j++)
    if(G.arcs[v][j].adj==1)
    {
    k = j;
    break;
    }
    return k;
    }

    void DFS(MGraph G, int v)
    {
    int j;
    cout << G.vexs[v] << " ";
    visited[v] = TRUE;
    for(j = 0; j < G.vexnum; j++)
    {
    if(G.kind == DG || G.kind == AG)
    if(!visited[j] && G.arcs[v][j].adj == 1)
    DFS(G, j);
    if(G.kind == DN || G.kind == AN)
    if(!visited[j] && G.arcs[v][j].adj != INFINITY)
    DFS(G, j);
    }
    }

    void DFSTraverse(MGraph G)
    {
    int v;
    for(v = 0; v < G.vexnum; v++)
    visited[v] = FALSE; //初始化为FALSE,遍历后改为TRUE
    for(v = 0; v < G.vexnum; v++)
    if(!visited[v])
    DFS(G, v);
    }

    void BFSTraverse(MGraph G)
    { //对以数组存储表示的图G进行广度优先搜索遍历
    Queue Q; // 附设队列Q
    int u, v, w;
    for (v = 0; v < G.vexnum; ++v)
    visited[v] = FALSE;
    InitQueue(Q, G.vexnum); //设置空队列Q
    for(v = 0; v < G.vexnum; ++v )
    if(!visited[v])
    { //从每一个未被访问的顶点出发进行广度优先搜索
    visited[v] = TRUE;
    cout << G.vexs[v] << " "; //访问输出图中第v个顶点
    EnQueue(Q, v); //v入队列
    while(!QueueEmpty(Q))
    {
    DeQueue(Q, u); //队头元素出队并置为u
    for(w = 0; w < G.vexnum; w++)
    if(G.arcs[u][w].adj && ! visited[w])
    {
    visited[w] = TRUE;
    cout << G.vexs[w] << " "; //访问输出图中第w个顶点
    EnQueue(Q, w); //当前访问的顶点w入队列Q
    }//if
    }//while
    }//if
    DestroyQueue(Q);
    }//BFSTraverse

    int main(void)
    {
    MGraph G;
    int i, j;
    CreateGraph(G);
    cout << "邻接矩阵为:" << endl;
    for(i = 0; i < G.vexnum; i++)
    {
    for(j = 0; j < G.vexnum; j++)
    {
    cout << G.arcs[i][j].adj << " ";
    }
    cout << endl;
    }
    cout << "深度优先遍历为:";
    DFSTraverse(G);
    cout << endl;
    cout << "广度优先遍历为:";
    BFSTraverse(G);
    cout << endl;
    return 0;
    }

  • 相关阅读:
    WPF Window对象的生命周期
    MVC 控制器中传递dynamic(对象) 给视图
    MVC 获取路由的 URL 参数值和默认值的集合。
    mvc路由配置.html结尾的伪静态
    javascript 模拟按键点击提交
    微信小程序调用接口返回数据或提交数据
    清理电脑文件夹中的Thumbs.db文件
    asp.net动态增加服务器端控件并提交表单
    c# asp.net 实现分页(pager)功能
    注册时发短信如何防止别人恶意调用短信接口
  • 原文地址:https://www.cnblogs.com/wwttsqt/p/7783205.html
Copyright © 2020-2023  润新知