zoukankan      html  css  js  c++  java
  • 图(Graph)的常用代码集合

    图的相关概念请查阅离散数学图这一章或者数据结构中对图的介绍。代码来自课本。

    /*Graph存储结构*/
    //邻接矩阵表示法
    #define MAX_VERTEX_NUM 20    /*最多顶点个数*/
    #define INFINITY 32768       /*表示极大值,即∞*/
    
    /*图的种类:DG表示有向图,DN表示有向网,DUG表示无向图,UDN表示无向网*/
    typedef enum {DG, DN, UDG, UDN} GraphKind;  /*枚举类型*/
    typedef char VertexData     /*假设顶点数据为字符型*/
    typedef struct ArcNode {
        AdjType adj;            /*对于无权图,用1或0表示是否相邻;对带权图,则为权值类型*/
        OtherInfo info;
    } ArcNode;
    typedef struct {
        VertexData vertex[MAX_VERTEX_NUM];    /*顶点向量*/
        ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];    /*邻接矩阵*/
        int vexnum,arcnum;
        GraphKind kind;
    } AdjMartrix;     /*(AdjMartrix Matrix Graph)*/
    /*采用邻接矩阵表示法创建有向图*/
    int LocateVertex(AdjMartrix *G, VertexData v) {     /*定位顶点位置函数*/
        int j = ERROR, k;
        for(k = 0; k < G->vexnum; k++) {
            if(G->vertex[k] == v) {
                j = k; break;
            }
        }
        return j;
    }
    
    int CreateDN(AdjMartrix *G) {
        int i,j,k,weight; VertexData v1,v2;
        scanf("%d,%d", &G->arcnum; &G->vexnum);     /*输入图的顶点数和弧数*/
        for(i = 0; i < G->vexnum; i++) {            /*初始化邻接矩阵*/
            for(j = 0; j < G->vexnum; j++) {
                G->arcs[i][j].adj = INFINITY;
            }
        }
        for(i = 0; i < G->vertex; i++) {      /*输入图的顶点*/
            scanf("%c", &G->vertex)[i];
        }
        for(k = 0; k < G->arcnum; k++) {      /*输入一条弧的两个顶点和权值*/
            scanf("%c,%c,%d", &v1,&v2,&weight);
            i = LocateVertex_M(G, v1);
            j = LocateVertex_M(G, v2);
            G->arcs[i][j].adj = weight;      /*建立弧*/
        }
        return OK;
    }
    //邻接表表示法
    #define MAX_VERTEX_NUM 20
    typedef enum {DG, DN, UDG, UDN} GraphKind;
    typedef struct ArcNode {
        int adjvex;                   /*该弧指向顶点的位置*/
        struct ArcNode *nextarc;      /*指向下一条弧的指针*/
        OtherInfo;
    } ArcNode;
    typedef struct VerNode {
        VertexData data;
        ArcNode *firstarc;
    } VerNode;
    typedef struct {
        VertexNode vertex[MAX_VERTEX_NUM];
        int vexnum,arcnum;
        GraphKind kind;
    } AdjList;     /*Adjacency List Graph*/
    //十字链表
    #define MAX_VERTEX_NUM 20
    typedef enum {DG, NG, UDG, UDN} GraphKind;
    typedef struct ArcNode {
        int tailvex,headvex;
        struct ArcNode *hlink, *tlink;
    } ArcNode;
    typedef struct VertexNode {
        VertexData data;
        ArcNode *firstin, *firstout;
    } VertexNode;
    typedef struct {
        VertexNode vertex[MAX_VERTEX_NUM];
        int vexnum,arcnum;     //图的顶点数和弧数
        GraphKind kind;
    } OrthList;
    /*创建图的十字链表*/
    void CrtOrthList(OrthList *g) {
    /*从终端输入n个顶点的信息和e条弧的信息,以建立一个有向图的十字链表*/
        scanf("%d,%d", &n,&e);    /*从键盘输入图的顶点个数和弧的个数*/
        g->vertex = n;
        g->vertex = e;
        for(i = 0; i < n; i++) {     /*初始化顶点结点*/
            scanf("%c", &(g->vertex[i].data));
            g->vertex[i].firstin = NULL;
            g->vertex[i].firstout = NULL;
        }
        for(k = 0; k < e; k++) {     /*创建弧结点,建立弧结点个顶点的连接*/
            scanf("%c,%c", &vt,&vh);
            i = LocateVertex(g, vt);
            j = LocateVertex(g, vh);
            p = (ArcNode *)malloc(sizeof(ArcNode));
            p->tailvex = i; p->headvex = j;
            p->tlink = g->vertex[i].firstout;
            g->vertex[i].firstout = p;
            p->hlink = g->vertex[j];
            g->vertex[j].firstin = p;
        }
    }    /*CrtOrthList*/
    /*邻接多重表*/
    #define MAX_VERTEX_NUM 20
    typedef struct EdgeNode {
        int mark,ivex,jvex;
        struct EdgeNode *ilink, *jlink;
    } EdgeNode;
    typedef struct {
        VertexData data;
        EdgeNode *firstedge;
    } VertexNode;
    typedef struct {
        VertexNode vertexp[MAX_VERTEX_NUM];
        int vernum,arcnum;
        GraphKind kind;
    } AdjMultiList;
    
    /*图的深度遍历算法*/
    #define True  1
    #define False 0
    #define Error -1
    #define OK    1
    int visited[MAX_VERTEX_NUM];     /*初始化标准数组*/
    
    void TraverseGraph(Graph g) {
    /*在图g中寻找未访问的顶点作为起始点,并调用深度优先搜索过程进行遍历。Graph表示图的
    一种存储结构,如邻接矩阵或者邻接表等*/
        for(vi = 0; vi < g.vexnum; vi++) Visited[vi] = False;    /*访问标志数组*/
        for(vi = 0; vi < g.vexnum; vi++) {    //循环调用深度优先遍历连通子图,若g是连通图,则此
            if(!visted[vi]) DepthFirstSearch(g,vi);    //仅调用一次
        }                                     
    } /*TraverseGraph*/
    /*深度优先遍历v0所在的连通子图*/
    void DepthFirstSearch(Graph g, int v0) {
        visit(v0); visit[v0] = True;     /*访问顶点v0,修改访问变量*/
    
        w = FirstAdjVertex(g, v0);
        while(w != -1) {
            if(!visited[w]) DepthFirstSearch(g, w);    /*递归调用DepthFirstSearch*/
            w = NextAdjVertex(g, v0, w);     /*找下一个邻接点*/ 
        }
    }     /*DepthFirstSearch*/
    /*采用邻接矩阵的DepthFirstSearch*/
    void DepthFirstSearch(AdjMartrix g, int v0) {
        visit(v0); visited[vo] = True;
        for(vj = 0; vj < g.vexnum; vj++) {
            if(!visited[vj] && g.arcs[v0][vj].adj  == 1) {    //未访问过且路径存在
                DepthFirstSearch(g, vj);
            }
        }
    }     /*DepthFirstSearch*/
    /*采用邻接表的DepthFiirstSearch*/
    void DepthFirstSearch(AdjList g, int v0) {
        visit(v0); visited[v0] = True;
        p = g.vertex[v0].firstarc;
        while(p != NULL) {
            if(!visited[p->adjvex]) DepthFirstSearch(g, p->adjvex);
            p = p->nextarc;
        }
    }     /*DepthFirstSearch*/
    /*非递归形式的DepthFirstSearch*/
    void DepthFirstSearch(Graph g, int v0) {
    /*从v0出发深度优化搜索图g*/
        InitStack(&s);
        Push(&S, v0);
        while(!is Empty(S)) {
            Pop(&S, &v);
            if(!visited[v]) {
                visit(v);
                visited[v] = True;
                w = FirstAdjVertex(g, v);
                while(w != -1) {
                    if(!visted[w]) {
                        Push(&S, w);
                    }
                    w = NextAdjVertex(g, v, w);     /*求v相对于w的下一个邻接点*/
                }
            }
        }
    }
    /*广度优先搜索图g中v0所在的连通子图*/
    void BreadthFirstSearch(Graph g, int v0) {
        visit(v0); visited[v0] = True;
        InitQueue(&Q);
        EnterQueue(&Q, v0);
        while(Empty(&Q, v0)) {
            DeleteQueue(&Q, &v);
            w = FirstAdjVertex(g, v);
            while(w != -1) {
                if(!visited[w]) {
                    visit(w); visited[w] = True;
                    EnterQueue(&Q, w);
                }
                w = NextAdjVertex(g, v, w);
            }
        }
    }
    /*图的应用*/
    /*深度优先找出从顶点u到v的简单路径*/
    int *pre;
    void one_path(Graph *G, int u, int v) {
        int i;
        pre = (int *)malloc(G->vexnum * sizeof(int));
        for(i = 0; i < G->vexnum; i++) {     /*初始化,置-1*/
            pre[i] = -1;
        }
        pre[u] = -2;           /*将pre[u]置-2,表示已访问过,且没有前驱*/
        DFS_path(G, u, v);     /*用深度优先算法找出一条从u到v的简单路径*/
        free(pre);
    }
    int DFS_path(Graph *G, int u, int v) {
        int j;
        for(j = firstadj(G, u)); j >= 0; j = nextadj(G, u, j)) {
            if(pre[j] == -1) {     //不等于-1则参数有误
                pre[j] = u;
                if(j == v) {
                    print_path(pre, v);   //从v0开始,沿着pre[]中保留的前驱指针输出路径(直到-2)
                }
                else if(DFS_path(G, j, v)); return 1;
            }
        }
        return 0;
    }
    /*求图的最小生成树*/
    /*prim算法(加点法)*/
    struct {
        int adjvex;
        int lowcost;
    } closedge[MAX_VERTEX_NUM];    /*求最小生成树时的辅助数组*/
    
    MiniSpanTree_Prim(AdjMartrix gn, int u) {
    /*从顶点u出发,按prim算法构造连通网gn的最小生成树,并输出生成时的每条边*/
        closedge[u].lowcost = 0;     /*初始化*, U = {u}*/
        for(i = 0; i < gn.vexnum; i++) {
            if(i != u) {             /*对V-U的顶点i,初始化closedge[i]*/
                closedge[i].adjvex = u;
                closedge[i].lowcost = gn.arcs[u][i].adj;    
            }
        }
        for(e = 1; e < gn.vexnum - 1; e++) {    /*找n-1条边*/
            v = Mimium(closedge);     /*closedge中存有当前最小边(u,v)的信息*/
            printf(u, v);     /*输出生成树的当前最小边(u,v)*/
            closedge[v].lowcost = 0;     /*将顶点v纳入U集合*/
            for(i = 0; i < gn.vexnum; i++) {     /*顶点v纳入U集合后,更新closedge[i]*/
                if(gn.arcs[v][i].adj < closedge[i].lowcost) {
                    closedge[i].lowcost = gn.arcs[v][i].adj;
                    closedge[i].adj = v;
                }
            }
        }
    
    }
  • 相关阅读:
    LNMP源码编译安装(centos7+nginx1.9+mysql5.6+php7)
    linux 最大文件查找
    Nginx 日志分享
    ZendGuardLoader安装
    移动端播放直播流(video.js 播放 m3u8 流)
    Linux下 PostgrelSQL 基本操作
    CenterOS7 安装Mysql8 及安装会遇到的问题
    Linux下 导出postgrelSql 数据库
    《编译程序设计原理与技术》笔记之自动机与正规表达式
    Linux定时检测内存,若使用率超过指标,重启Tomcat并清空内存
  • 原文地址:https://www.cnblogs.com/wanghongze95/p/13842652.html
Copyright © 2011-2022 走看看