zoukankan      html  css  js  c++  java
  • 数据结构 实验四 图

    数据结构 实验四  图

    这次给出图论部分的数据结构相关代码,由于图结构不像树结构那样具有明显的层次性,较实验三的二叉树来说会复杂一些;在图的存储结构中,邻接矩阵的存储方式较为简单明了,但是在实际开发中往往由于其会导致占用大量的内存空间而被舍弃,但邻接表这样的链式结构就解决了这一的问题,所以对邻接表的掌握较为重要。

    下面放出图的相关代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    /*包含数据结构的预定义常量和类型P10 */
    #include "Datahead.h"
    
    /* P161 图的数组(邻接矩阵)存储表示*/
    #define INFINITY INT_MAX    /*无穷大 */
    #define INT_MAX 999            /*最大整数 */
    #define MAX_VERTEX_NUM 20    /*图的最大顶点数*/
    
    typedef enum{DG,DN,UDG,UDN} GraphKind;        /*有向图,有向网,无向图,无向网*/
    
    typedef int VRType;                            /*网络权值暂定为整数型*/
    typedef char InfoType;                        /*备用*/
    typedef char VertexType;                    /*顶点名称,字符型*/
    
    typedef struct ArcCell{
      VRType adj;                /*顶点关系类型:无向图,用0或1表示是否相邻;对于带权图,则为权值类型*/
      InfoType *info;            /*该弧相关信息的指针*/
    }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    
    
    typedef struct{
      VertexType vexs[MAX_VERTEX_NUM];        /*顶点向量*/
      AdjMatrix arcs;                        /*邻接矩阵*/
      int vexnum,arcnum;                    /*图的当前顶点数和弧数*/
      GraphKind kind;                        /*图的种类标志*/
    }MGraph;
    
    
    /*P163 图的邻接表存储表示*/
    typedef struct ArcNode{
      int adjvex;
      struct ArcNode *nextarc;
      InfoType       *info;
    }ArcNode;
    
    typedef struct VNode{
      VertexType data;
      ArcNode    *firstarc;
    }VNode,AdjList[MAX_VERTEX_NUM];
    
    typedef struct{
      AdjList vertices;
      int vexnum,arcnum;
      int kind;
    }ALGraph;
    
    
    /*算法7.4 7.5 深度遍历图*/
    /* --- 算法7.4和7.5使用的全局变量 --- */
    bool visited[MAX_VERTEX_NUM];        /*  访问标志数组 */
    Status (* VisitFunc)(int v);        /*  函数变量 */
    
    /*p61队列定义*/
    typedef struct QNode{
        int data;                    /*图中结点用结点数组中的位置表示,为整数*/
        struct QNode *next;
    }QNode, *QueuePtr;
    
    typedef struct{
        QueuePtr front;
        QueuePtr rear;
    }LinkQueue;
    
    
    /*函数原型声明*/
    Status CreateGraph(MGraph *G);
    Status CreateDG(MGraph *G);
    Status CreateDN(MGraph *G);
    Status CreateUDG(MGraph *G);
    Status CreateUDN(MGraph *G);
    void OutputMG(MGraph G);
    int LocateVex(MGraph G, VertexType v1);
    
    Status CreateALGraph(MGraph *M, ALGraph *AL);
    void OutputAL(ALGraph AL);
    void DFSTraverse(ALGraph G, Status (*Visit)(int v));
    void DFS(ALGraph G, int v);
    int FirstAdjVex(ALGraph G, int v);
    int NextAdjVex(ALGraph G, int v, int w);
    Status PrintInt(int e);   /*Visit 函数*/
    
    void BFSTraverse(ALGraph G, Status (*Visit)(int v )); /*   算法7.6 */
    Status InitQueue(LinkQueue *Q);
    Status EnQueue(LinkQueue *Q,int e);
    Status DeQueue(LinkQueue *Q,int *e);
    Status QueueEmpty(LinkQueue Q);
    
    
    MGraph *p;
    MGraph G;        /*全局变量  图G*/
    ALGraph *A,AL;    /*邻接表变量*/
    
    // 主函数
    void main()
    {
        p=&G;
        system("graftabl 936");/*调用MS_DOS中文支持*/
        printf("
    **********************图**********************
    
    ");
    
        if ( CreateGraph(p) ) OutputMG(G);
        A=&AL;
        if ( CreateALGraph(p, A) ) OutputAL(AL);
    
        printf("
    深度遍历为:");
        DFSTraverse(AL, PrintInt);
        printf("
    广度遍历为:");
        BFSTraverse (AL, PrintInt );
        getchar();
    }
    
    Status CreateGraph(MGraph *G){  /*  算法7.1 */
        /*  采用数组(邻接矩阵)表示法,构造图G*/
    
        int k;   
        printf("请选择创建图的类型 	1:有向图DG;
    			2:有向网DN;
    			3:无向图UDG;
    			4:无向网UDN.
    ");
        scanf("%d", &k);
        switch(k){
            case  1: return CreateDG(G);   /*  构造有向图G */
            case  2: return CreateDN(G);   /*  构造有向网G */
            case  3: return CreateUDG(G);  /*  构造无向图G */
            case  4: return CreateUDN(G);  /*  构造无向网G,算法7.2 */
            default   : return ERROR;
        }
    } /*  CreateGraph */
    
    Status CreateDG(MGraph *G) {/*   改造自算法 7.2 */
      /*  采用数组(邻接矩阵)表示法,构造有向图 */
      int i,j,k,w; 
      VertexType  v1,v2; 
      printf("请输入顶点个数G->vexnum :" );  scanf("%d",&G->vexnum);
      printf("请输入弧的条数G->arcnum :");   scanf("%d",&G->arcnum);
      getchar();  /*** 加上此句getchar()!!! ***/
      /*  scanf("%d,%d,%d",&G.vexnum, &G.arcnum, &IncInfo);       */
      for (i=0; i<G->vexnum; i++ ) {
        printf("请输入顶点G->vexs[%d]的名称(字符型):",i);
        scanf("%c",&G->vexs[i]);
        getchar();
      } /*  构造顶点向量 */
      for (i=0; i<G->vexnum; ++i )  /*  初始化邻接矩阵 ,全部赋值为0*/
        for (j=0; j<G->vexnum; ++j ) {
          G->arcs[i][j].adj = 0; /* {adj,info} */
          G->arcs[i][j].info= NULL;
        }
      for (k=0; k<G->arcnum; ++k ) {  /*  构造邻接矩阵
        printf("v1 (char) : ");  scanf("%c", &v1);getchar();
        printf("v2 (char) : ");  scanf("%c", &v2);getchar();
        printf("w (int) : " );   scanf("%d", &w); getchar();    */
        printf("请依次输入弧尾、弧头顶点名称(如,a b):" );
        scanf("%c %c", &v1,&v2);getchar();
                                 /*  输入一条边依附的顶点及权值 */
        i = LocateVex(*G, v1);  j = LocateVex(*G, v2);
              /*  确定v1和v2在G中位置 */
        G->arcs[i][j].adj = 1;                /*  弧<v1,v2>的权值为1,表示两点相邻接 */
        /*  if (IncInfo) scanf(G.arcs[i][j].info); /*  输入弧含有相关信息 */ 
    
      }
      G->kind=DG;
      return OK;
    } /*  CreateDG */
    
    Status CreateDN(MGraph *G) {/*   改造自算法 7.2 */
      /*  采用数组(邻接矩阵)表示法,构造有向图 */
      int i,j,k,w; 
      VertexType  v1,v2; 
      printf("请输入顶点个数G->vexnum :" );  scanf("%d",&G->vexnum);
      printf("请输入弧的条数G->arcnum :");   scanf("%d",&G->arcnum);
      getchar();  /*** 加上此句getchar()!!! ***/
      /*  scanf("%d,%d,%d",&G.vexnum, &G.arcnum, &IncInfo);       */
      for (i=0; i<G->vexnum; i++ ) {
        printf("请输入顶点G->vexs[%d]的名称(字符型):",i);
        scanf("%c",&G->vexs[i]);
        getchar();
      } /*  构造顶点向量 */
      for (i=0; i<G->vexnum; ++i )  /*  初始化邻接矩阵 ,全部赋值为0*/
        for (j=0; j<G->vexnum; ++j ) {
          G->arcs[i][j].adj = 0; /* {adj,info} */
          G->arcs[i][j].info= NULL;
        }
      for (k=0; k<G->arcnum; ++k ) {  /*  构造邻接矩阵*/
            printf(" 请依次输入第%d条边依附的两个顶点,以及该边的权值:", k+1);
            scanf("%c %c %d", &v1, &v2, &w);
            getchar();
            i = LocateVex(*G, v1);    
            j = LocateVex(*G, v2);
            G->arcs[i][j].adj = w;
        /*  if (IncInfo) scanf(G.arcs[i][j].info); /*  输入弧含有相关信息 */ 
      }
      G->kind=DN;
      return OK;
    } /*  CreateDN */
    
    Status CreateUDG(MGraph *G) {/*   改造自算法 7.2 */
      /*  采用数组(邻接矩阵)表示法,构造无向图 */
      int i,j,k;
      VertexType  v1,v2; 
      printf("请输入顶点个数G->vexnum :" );  scanf("%d",&G->vexnum);
      printf("请输入弧的条数G->arcnum :");   scanf("%d",&G->arcnum);
      getchar();  /*** 加上此句getchar()!!! ***/
      /*  scanf("%d,%d,%d",&G.vexnum, &G.arcnum, &IncInfo);       */
      for (i=0; i<G->vexnum; i++ ) {
        printf("请输入顶点G->vexs[%d]的名称(字符型):",i);
        scanf("%c",&G->vexs[i]);
        getchar();
      } /*  构造顶点向量 */
      for (i=0; i<G->vexnum; ++i )  /*  初始化邻接矩阵 ,全部赋值为0*/
        for (j=0; j<G->vexnum; ++j ) {
          G->arcs[i][j].adj = 0; /* {adj,info} */
          G->arcs[i][j].info= NULL;
        }
      for (k=0; k<G->arcnum; ++k ) {  /*  构造邻接矩阵
        printf("v1 (char) : ");  scanf("%c", &v1);getchar();
        printf("v2 (char) : ");  scanf("%c", &v2);getchar();
        printf("w (int) : " );   scanf("%d", &w); getchar();    */
        printf("请依次输入弧尾、弧头顶点名称(如,a b):" );
        scanf("%c %c", &v1,&v2);getchar();
                                 /*  输入一条边依附的顶点及权值 */
        i = LocateVex(*G, v1);  j = LocateVex(*G, v2);
              /*  确定v1和v2在G中位置 */
        G->arcs[i][j].adj = 1;                /*  弧<v1,v2>的权值为1,表示两点相邻接 */
        /*  if (IncInfo) scanf(G.arcs[i][j].info); /*  输入弧含有相关信息 */ 
        G->arcs[j][i].adj = G->arcs[i][j].adj; /*  置<v1,v2>的对称弧<v2,v1> */
      }
      G->kind=UDG;
      return OK;
    } /*  CreateUDG */
    
    
    Status CreateUDN(MGraph *G) {/*   算法 7.2 */
      /*  采用数组(邻接矩阵)表示法 */
        int i, j, k;
        VRType w;
        VertexType  v1, v2; 
        printf("请输入顶点个数G->vexnum :" );  scanf("%d", &G->vexnum);
        printf("请输入弧的条数G->arcnum :");   scanf("%d", &G->arcnum);
        getchar();
        // 构造顶点向量
        for( i = 0; i < G->vexnum; i++ )
        {
            printf("请输入顶点G->vexs[%d]的名称(字符型):", i);
            scanf("%c", &G->vexs[i]);
            getchar();
        }
        // 初始化邻接矩阵
        for( i = 0; i < G->vexnum; i++ )
        {
            for( j = 0; j < G->vexnum; j++ )
            {
                G->arcs[i][j].adj = 0;
                G->arcs[i][j].info = NULL;
            }
        }
        // 构造邻接矩阵
        for( k = 0; k < G->arcnum; ++k )
        {
            printf(" 请依次输入第%d条边依附的两个顶点,以及该边的权值:", k+1);
            scanf("%c %c %d", &v1, &v2, &w);
            getchar();
            i = LocateVex(*G, v1);    
            j = LocateVex(*G, v2);
            G->arcs[i][j].adj = w;
            G->arcs[j][i] = G->arcs[i][j];
        }
        G->kind = ::UDN;
        return OK;
    }
    
    int LocateVex(MGraph G,VertexType v1){
        int i;
        for (i = 0;i <= G.vexnum; i++) {
          if (v1 == G.vexs[i]) return i;
        }
        return 0;
    }
    
    /*建立无向图邻接矩阵*/
    
    /*输出邻接矩阵*/
    void OutputMG(MGraph G)
    {
        int i,j;
        printf("
    邻接矩阵为:");
        for(i=0;i<G.vexnum;i++)
        {
            printf("
    ");
            for(j=0;j<G.vexnum;j++) printf("%5d",G.arcs[i][j]);
        }
    }
    
    /*创建邻接表,数据来源于已知的邻接矩阵*/
    Status CreateALGraph(MGraph *M, ALGraph *AL){
      int i,j;
      ArcNode *head,*p;
      AL->vexnum=M->vexnum;
      AL->arcnum=M->arcnum;
      AL->kind=M->kind;
      for (i=0;i<M->vexnum;i++) AL->vertices[i].data=M->vexs[i];
      head = (ArcNode *)malloc(sizeof(ArcNode)); /*单链表 头指针*/
      for (i=0;i<M->vexnum;i++)
        {head->nextarc=NULL;
         for (j=0;j<M->vexnum;j++)
          {
           if ((M->arcs[i][j].adj!=INFINITY) &&(M->arcs[i][j].adj!=0))
             {p = (ArcNode *)malloc(sizeof(ArcNode));
              p->info=M->arcs[i][j].info;
              p->nextarc=head->nextarc;
              p->adjvex=j;/*j顶点*/
              head->nextarc=p;   /*逆序插入各弧*/
             }
          }
        AL->vertices[i].firstarc = head->nextarc;
      }
      free(head);
      return OK;
    }
    
    void OutputAL(ALGraph AL){
      int i,j;
      ArcNode *p;
      printf("
    邻接表为:");
      for (i=0;i<AL.vexnum;i++)
      { printf("
    顶点%c->",AL.vertices[i].data);
        p=AL.vertices[i].firstarc;
        while(p)     /*输出单链表*/
         { printf("%5d",p->adjvex);
           p=p->nextarc;
         }
      }
    }
    
    void DFSTraverse(ALGraph G, Status (*Visit)(int v)) {  /*  算法7.4 */
     /*  对图G作深度优先遍历。     对尚未访问的顶点调用DFS */
        int v;
        VisitFunc = Visit;
        for( v = 0; v < G.vexnum; v++ )    visited[v] = FALSE;        // 初始化访问标记数组
        for( v = 0; v < G.vexnum; v++ )
        {
            if( !visited[v] )        
                DFS(G, v);            // 对尚未访问的顶点调用DFS
        }
    }
    
    void DFS(ALGraph G, int v) {  /*  算法7.5 */
       /*  从第v个顶点出发递归地深度优先遍历图G。*/
        visited[v] = TRUE;
        VisitFunc(v);
        int w;
        for( w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w) )
        {
            if( !visited[w] )
                DFS(G, w);
        }
    }
    
    int FirstAdjVex(ALGraph G,int v){
        ArcNode *p;
        p = G.vertices[v].firstarc;
        if(p != NULL) return p->adjvex;
        else  return -1;/*p为空*/
    }
    
    int NextAdjVex(ALGraph G,int v,int w){
        ArcNode *p;
        p = G.vertices[v].firstarc;
        while(p){
          if ((p->adjvex == w)&&(p->nextarc != NULL)) return p->nextarc->adjvex;
          p = p->nextarc;
        }
        return -1;
    }
    
    // 此处改写了 Visit 函数,改为输出顶点名称,即data中的信息
    Status PrintInt(int e){   /*Visit 函数*/
        //printf("  %d",e);           
        printf("  %c",AL.vertices[e].data);    //输出值,以强调visit函数
        return OK;
    }
    
    
    void BFSTraverse(ALGraph G, Status (*Visit)(int v )) {/*   算法7.6 */
      /*  按广度优先非递归遍历图G。使用辅助队列Q和访问标志数组visited。 */
        int v, u, w;
        LinkQueue Q, *pQ;
        pQ = &Q;
        for( v = 0; v < G.vexnum; v++ )    visited[v] = FALSE;        // 初始化访问标记数组
        InitQueue(&Q);                                            // 置空的辅助队列
        for( v = 0; v < G.vexnum; v++ )
        {
            if( !visited[v] )
            {
                visited[v] = TRUE;    Visit(v);
                EnQueue(&Q, v);
                while (!QueueEmpty(Q))
                {
                    DeQueue(&Q, &u);
                    for( w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w) )
                        if( !visited[w] )
                        {
                            visited[w] = TRUE;
                            Visit(w);
                            EnQueue(&Q, w);
                        }
                }
            }
        }
    } /*  BFSTraverse */
    
    Status InitQueue(LinkQueue *Q){     /*生成头结点*/
        Q->front = Q->rear =(QueuePtr)malloc(sizeof(QNode));
        Q->front->next = NULL;
        return OK;
    }
    
    Status EnQueue(LinkQueue *Q, int e){
        QueuePtr p;
        p=(QueuePtr)malloc(sizeof(QNode));
        p->data=e;    p->next=NULL;
        Q->rear->next=p;
        Q->rear=p;
        return OK;
    }
    
    Status DeQueue(LinkQueue *Q,int *e){
        QueuePtr p;
        if (Q->front==Q->rear) return ERROR;
        p=Q->front->next;
        *e=p->data;
        Q->front->next=p->next;
        if (Q->rear==p) Q->rear=Q->front;
        free(p);
        return OK;
    }
    
    Status QueueEmpty(LinkQueue Q){
        if (Q.rear==Q.front) return TRUE;
        else return FALSE;
    }

    可以直接复制上述代码,也可也去我的网盘下载该cpp源文件(含”DataHead.h“头文件)

    http://pan.baidu.com/s/1GJsZb

  • 相关阅读:
    tomcat 启动 报错Neither the JAVA_HOME nor the JRE_HOME environment variable is definedtemp
    tomcat linux 加入服务自动启动
    registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
    tomcat 8 加 struts2的 java.lang.NoSuchFieldException: resourceEntries
    tomcat Can't create cache file!
    tomcat 部署时修改服务器时间
    tomcat java变量环境设置
    scrapy 动态IP、随机UA、验证码
    scrapy xpath、正则表达式、css选择器
    Saltstack windows可视化操作(十四)
  • 原文地址:https://www.cnblogs.com/uppercloud/p/DataStructure_Graph.html
Copyright © 2011-2022 走看看