zoukankan      html  css  js  c++  java
  • c_ 数据结构_图_邻接矩阵

    程序主要实现了图的深度遍历和广度遍历。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define OVERFLOW -2
    #define ERROR 0
    #define OK 1
    #define Length (q.rear+1)%QUEUE_MAXSIZE     //队满
    #define MAX_VERtEX_NUM 20                   //顶点的最大个数
    #define QUEUE_MAXSIZE 100
    #define Queue_increment 10
    
    typedef struct QNode{
        int data;
        struct QNode *next;
    }QNode,*QueuePtr;
    
    typedef struct{
        QueuePtr front;   //队头指针
        QueuePtr rear;    //队尾指针
    }LinkQueue;
    //-------------------------------------------------------------------------------------------------------------
    typedef struct {
        int adj;                             //对于无权图,用 1 或 0 表示是否相邻;对于带权图,直接为权值。
    }ArcCell,AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];
    
    typedef struct {
        char vexs[MAX_VERtEX_NUM];        //存储图中顶点数据
        AdjMatrix arcs;                         //二维数组,记录顶点之间的关系
        int vexnum,arcnum;                      //记录图的顶点数和弧(边)数
    }MGraph;
    //---------------------------------------------------------------------------
    // 矩阵打印关系
    void PrintGrapth(MGraph &G){
        int i,j;
        for (i = 0; i < G.vexnum;++i){
            printf("%d",G.vexs[i]);
        }
        printf("顶点间的关系:
    ");
        for (i = 0; i < G.vexnum; ++i){
            for (j = 0; j < G.vexnum; ++j){
                printf("%d ", G.arcs[i][j].adj);
            }
            printf("
    ");
        }
    }
    //---------------------------------------------------------------------------
    //根据顶点本身数据,判断出顶点在二维数组中的位置
    int LocateVex(MGraph &G,int v){
        //遍历一维数组,找到变量v
        for (int i=0; i<G.vexnum; ++i) {
            if (G.vexs[i]==v) {
                return i;
            }
        }
        return -1; //如果找不到,返回-1  
    }
    //构造无向图
    int CreateDN(MGraph &G){
        int i,j,k,m,n,x;int v1,v2;//char a[2];
        printf("请输入总顶点数n和总边数:");
        scanf("%d",&(G.vexnum));        // 输入总顶点数,总边数
        scanf("%d",&(G.arcnum));
        x=G.vexnum;
        if(G.vexnum<20 && G.arcnum<=(x*(x-1)/2)){
            printf("请(回车)输入 %d 个顶点的值:
    ",G.vexnum);
            for (i=0; i<G.vexnum; i++) {      // 循环输入顶点值
                scanf("%d",&(G.vexs[i]));
            }        
            for (i=0; i<G.vexnum; ++i) {        // 初始化邻接矩阵
                for (j=0; j<G.vexnum; ++j) {
                    G.arcs[i][j].adj=0;
                }
            }
            printf("
    请实现 %d 条边的连接:
    ",G.arcnum);
            for (k=0;k<G.arcnum; ++k) {     // 构造邻接矩阵
                printf("
    请输入哪'两个'顶点要进行连接边:");
                fflush(stdin);
                scanf("%d",&v1);
                n=LocateVex(G, v1);    //定位顶点
                scanf("%d",&v2);
                m=LocateVex(G, v2);
                while (m==-1||n==-1) {
                       printf("没有这样的顶点,请重新输入:");
                    fflush(stdin);
                    scanf("%d",&v1);
                    n=LocateVex(G, v1);    //定位顶点
                    scanf("%d",&v2);
                    m=LocateVex(G, v2);
            //        if(m!=-1&&n!=-1){break;    }
                }
                while(G.arcs[n][m].adj==1){
                    printf("
    !!!两顶点已经被连接!!!
    ");
                    printf("请重新输入两顶点:");
                    fflush(stdin);
                    scanf("%d",&v1);
                    n=LocateVex(G, v1);    //定位顶点
                    scanf("%d",&v2);
                    m=LocateVex(G, v2);
            //        if(G.arcs[n][m].adj!=1){break;    }
                    while (m==-1||n==-1) {
                           printf("没有这样的顶点,请重新输入:");
                        fflush(stdin);
                        scanf("%d",&v1);
                        n=LocateVex(G, v1);    //定位顶点
                        scanf("%d",&v2);
                        m=LocateVex(G, v2);
                //        if(m!=-1&&n!=-1){break;    }
                    }
                }
                G.arcs[n][m].adj=G.arcs[m][n].adj=1;    //无向图的二阶矩阵沿主对角线对称
            }
        }else{
            printf("
    !!!您输入的总顶点数 大于 20 了或者是输入的总边数 不符合 n(n-1)/2 !!!
    ");
            CreateDN(G);
        }
        return OK;
    }
    //-------------------------------------------------------------------------------------------------
    int visited[MAX_VERtEX_NUM];   // 辅助数组
    // 遍历节点
    void DFS(MGraph &G,int v){    
        int j;
        printf("访问到顶点:%d
    
    ",G.vexs[v]);   // 表示顶点被访问过了
        visited[v]=1;
        for(j=0;j<G.vexnum;++j){        
            if(G.arcs[v][j].adj!=0 && visited[j]==0){   // 如果有邻接点则继续递归
                DFS(G,j);
            }
        }
    }
    
    // 顶点的非连通图的深度遍历
    int DFSTraverse(MGraph &G){   
        int n=0,v,x,j,m;
        for(v=0;v<G.vexnum;v++) visited[v]=0;    // 把所有的标记置为0
        printf("
    请输入遍历起点:
    ");
        scanf("%d",&x);
        printf("遍历起点为:%d 
    ",x);
        m = LocateVex(G,x);
        if(m==-1){
            printf("
    !!!您输入的起点不在顶点表内!!!
    ");
            DFSTraverse(G);
        }
        //n=LocateVex(G,x);
        visited[m]=1;    
        for(j=0;j<G.vexnum;++j){        
            if(G.arcs[n][j].adj!=0 && visited[j]==0){   // 如果有邻接点则继续递归
                DFS(G,j);
            }
        }
        //DFS(G,m);
        for(v=0;v<G.vexnum;++v){     // 判断是否还有没有被遍历的图
            if(visited[v]==0){
                DFS(G,v);    // 调用DFS遍历单个图
            }
        }
        return OK;
    }
    //-------------------------------------------------------------------------------------
    //构建空队
    int InitQueue_Q(LinkQueue &Q){
        Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
        if(!Q.front){
            printf("队存储空间分配失败!!");
            exit(OVERFLOW);
        }
        Q.front->next=NULL;
        return OK;
    }
    //队尾插入元素
    int EnQueue_Q(LinkQueue &Q,int &e){  
        QueuePtr p;
        p=(QueuePtr)malloc(sizeof(QNode));
        if(!p){                   //存储分配失败
            printf("队存储空间分配失败!!!
    ");
            exit(OVERFLOW);   
        }
        p->data=e;                          //e赋值给p指向的空间
        p->next=NULL;                     //p指向NULL
        Q.rear->next=p;
        Q.rear=p;                           //将p赋给Q
        return OK;
    }
    // 删除队列头元素
    int DeQueue_Q(LinkQueue &Q,int &e){
        QNode *P;
        if(Q.front==Q.rear) return ERROR;
        P=Q.front->next ; 
        e=P->data;       
        Q.front ->next =P->next;          //将原对头的后继p->next赋值给头结点后继
        if(Q.rear ==P)                 //当队列中只有一个元素时,q->rear指向头结点
            Q.rear =Q.front;
        free(P);
        return OK;
    }
    // 队判空
    int QueueEmpty(LinkQueue Q)
    {
        if(Q.front->next==NULL)
            return ERROR;
        else
            return OK;    
     }
    //-----------------------------------------------------------------------------------------------------
    // BFSTraversed调用BFS每一个节点都被访问
    void BFS(MGraph &G,int i){
        int j;
        LinkQueue Q;
        InitQueue_Q(Q);
        if(visited[i]==0){    //未访问过该顶点     
            printf("访问到顶点:%d
    
    ",G.vexs[i]);
            visited[i]=1;      // 置1
            EnQueue_Q(Q,i);      //将其入队列 
            while(QueueEmpty(Q)){  // 循环队不为空QueueEmpty返回1
                DeQueue_Q(Q,i);    //将队头元素出队列,置为v
                for(j=0;j<G.vexnum;j++){
                    if(G.arcs[i][j].adj!=0 &&visited[j]==0){      //未访问过的邻接点 
                        printf("顶点走到的值:%d
    
    ",G.vexs[j]);   // i 为v中未被访问的邻接点                    
                        visited[j]=1;   // 访问置1
                        EnQueue_Q(Q,j);         //入队列 
                    }    
                } 
            } 
        }
    }
    // 广度优先遍历图
    int BFSTraverse(MGraph &G)
    {
     
        int i,v,j,m;char x;
        LinkQueue Q;
        InitQueue_Q(Q);
        for(v=0;v<G.vexnum;v++){   // 辅助数组置零
            visited[v]=0;
        }
        printf("
    请输入遍历起点:
    ");
        scanf("%d",&x);
        printf("遍历起点为:%d 
    ",x);
        m=LocateVex(G,x);
        if(m==-1){
            printf("
    !!!您输入的起点不在顶点表内!!!
    ");
            BFSTraverse(G);
        }
        visited[m]=1;
            EnQueue_Q(Q,m);      //将其入队列 
            while(QueueEmpty(Q)){  // 循环队不为空QueueEmpty返回1
                DeQueue_Q(Q,m);    //将队头元素出队列,置为v
                for(j=0;j<G.vexnum;j++){
                    if(G.arcs[m][j].adj!=0 &&visited[j]==0){      //未访问过的邻接点 
                        printf("顶点走到的值:%d
    
    ",G.vexs[j]);   // i 为v中未被访问的邻接点                    
                        visited[j]=1;   // 访问置1
                        EnQueue_Q(Q,j);         //入队列 
                    }    
                } 
            } 
        for(i=0;i<G.vexnum;i++){   // 保证所有节点被访问
            BFS(G, i );
        }
        return OK;
    } 
     //操作菜单
    void OperateMenu(){      
    
        printf("
    
    --------------请选择元素处理方式---------
    
    ");
        printf("!!!!!注:测试程序过程中,输入应全为数字!!!!!
    
    ");
        printf("0> :退出
    
    ");
        printf("1>: 深度遍历
    
    ");
        printf("2>: 广度遍历
    
    ");
        printf("3>: 输出邻接矩阵
    
    ");
        printf("(注:选择过程中应为数字)
    
    ");
        printf("请选择对元素的处理:");
    }
    void main() {
        MGraph G;//建立一个图的变量
        int w=0,k,boo=1;
        printf("请用户选择创建图 或 退出程序:
    
    ");
        printf("注:程序测试过程中输入应全为数字
    
    ");
        printf("创建图请输入:'1'
    
    ");
        printf("退出请选择'0'或 其它!!
    
    ");
        printf("请选择:");
        scanf("%d",&w);
        if(w==1){
            boo=CreateDN(G);
            if(boo)
                printf("
    建图成功!!!
    ");
            else
                printf("
    建图失败!!!
    ");
            OperateMenu();
            scanf("%d",&k);
            while(k){
                switch(k){
                case 0:break;
                case 1:boo=DFSTraverse(G);    // 深度遍历
                    if(boo)
                        printf("
    深度遍历成功!!!
    ");
                    else
                        printf("
    深度遍历失败!!!
    ");
                    break;
                case 2:boo=BFSTraverse(G);        // 广度遍历
                    if(boo)
                        printf("
    广度遍历成功!!!
    ");
                    else
                        printf("
    广度遍历失败!!!
    ");
                    break;
                case 3:PrintGrapth(G);
                }
                OperateMenu();
                scanf("%d",&k);
            } 
        }
    }
  • 相关阅读:
    linux vim编辑
    jQuery Ajax 操作函数
    导出excel表功能
    jquery 分页控件功能
    数据绑定后细节处理
    删除数据库日志文件的操作语句
    SqlHelper.cs
    c#中$.ajax的使用
    SpringBoot 获取微信小程序openid
    Arduino IDE 开发 ESP-01S/ESP-01物联网实战检测温度湿度上传MQTT服务器
  • 原文地址:https://www.cnblogs.com/Vera-y/p/11491650.html
Copyright © 2011-2022 走看看