C语言利用图的邻接表的存储方式实现求有向图的入度和出度以及无向图的度数

Description

图采用邻接表为存储结构,图中的顶点数为n(0<n<=20),n个顶点的信息依次为 0,1,...,n-1。

编写程序,输入图的类型(0:无向图,1:有向图)、图中顶点数、边数、边的偶对,建立图的邻接表。如果是无向图,计算并输出每个顶点的度;如果是有向图,计算并输出每个顶点的的入度和出度。

Input

输入:

图的类型(0 或1)

顶点数,边数

顶点偶对 (每行一个偶对,如 vi,vj   表示一条边或者弧)

Output

输出:

无向图则依次输出每个顶点的度,以空格分隔。

有向图则依次输出每个顶点的入度,以空格分隔。

换行依次输出每个顶点的出度,以空格分隔。

Sample Input

1
4,4
0,1
0,2
2,3
3,0

Sample Output

1 1 1 1
2 0 1 1

根据题目的要求,我们先画出样例的图形如下

 代码和注释如下,首先创建结构体

#include <stdio.h>
#include <stdlib.h>
#define Max_Vertex_Num 100
typedef struct ArcNode{
    int adjvex; //此题用不到
    struct ArcNode *nextarc;//下一个节点
    int weight;//权重-此题用不到
}ArcNode;
/*表头节点*/
typedef struct VNode{
    int vertex;//表头数组的数据
    ArcNode *firstarc;//表头数组的表头节点域
}VNode; 

typedef VNode Adjlist[Max_Vertex_Num];//VNode构成的表头节点数组

/*整个邻接表*/
typedef struct{
    Adjlist adjlist;//每个定点后面的链表,记录关联点
    int vexnum,arcnum;//顶点数和边数
}ALGraph;

主函数的结构如下,先输入图的类型(gType)

int main()
{
    ALGraph G;
    int gType;//定义类型 0是无向图,1是有向图
    scanf("%d",&gType);
    CreateALGraph(&G,gType);
    
    if(gType==0)
        CountOutDegree(&G);//计算出度等同于计算所有度数
    else{
        CountInDegree(&G);//计算入度
        CountOutDegree(&G);//计算出度
    }
    return 0;
}

有了主函数的大致结构,应该知道先创建一个图吧,我们需要两个函数LocateVex获取输入的向量对是在函数的哪一行

然后根据输入的图的类型分类创建图

int LocateVex(ALGraph *G,int u){
    int i;
    for(i = 0; i<G->vexnum;++i)
    {
        if(G->adjlist[i].vertex == u)
        {
            return i;
        }
    }
    return -1;
}
/*创建图*/
void CreateALGraph(ALGraph *G,int gType)
{
    ArcNode *p;
    int i,j,k;
    int v1,v2;

    scanf("%d,%d",&G->vexnum,&G->arcnum); //输入顶点数和边数

    if(gType==0)
    {
        for(k=0;k<G->vexnum;k++)
        {
            G->adjlist[k].vertex = k;
            G->adjlist[k].firstarc = NULL;
        }
        k = 0;
        while(k<G->arcnum){
            scanf("%d,%d",&v1,&v2);
            k++;
            i = LocateVex(G,v1);
            j = LocateVex(G,v2);
            /*给第i的表头添加数据是j的节点*/
            p=(ArcNode*)malloc(sizeof(ArcNode));
            p->adjvex = j;
            p->nextarc = G->adjlist[i].firstarc;
            G->adjlist[i].firstarc = p;
            /*给第j的表头添加数据是i的节点*/
            p=(ArcNode*)malloc(sizeof(ArcNode));
            p->adjvex = i;
            p->nextarc = G->adjlist[j].firstarc;
            G->adjlist[j].firstarc = p;
        }
    }else{
         for(k=0;k<G->vexnum;k++)
        {
            G->adjlist[k].vertex = k;
            G->adjlist[k].firstarc = NULL;
        }
        k = 0;
        while(k<G->arcnum){
            scanf("%d,%d",&v1,&v2);
            k++;
            i = LocateVex(G,v1);
            j = LocateVex(G,v2);
            /*给第i的表头添加数据是j的节点——有向图,不需要给j添加i数据的节点了*/
            p=(ArcNode*)malloc(sizeof(ArcNode));
            p->adjvex = j;
            p->nextarc = G->adjlist[i].firstarc;
            G->adjlist[i].firstarc = p;
        }
    }
}

怎么求出度和入度呢?代码如下!

/*计算出度*/
void CountOutDegree(ALGraph *G){
    int i,j,k;
    int count1 = 0;
    ArcNode *p;
    //根据无向图的结构,表体中有几个节点,就有几度
    for(i=0;i<G->vexnum;i++)
    {
        int degree = 0;
        p = G->adjlist[i].firstarc;
        while(p!=NULL)
        {
            degree++;
            p=p->nextarc;
        }
        
        
        /*操蛋的输出格式!*/
        if(i!=G->vexnum-1)
            printf("%d ",degree);
        else
            printf("%d",degree);
            
    }
}
/*计算入度*/
void CountInDegree(ALGraph *G)
{
    ArcNode *p;
    int i;
    int j;
    //数组存放每个顶点的入度数量,赋初始值都为0
    int arr[G->vexnum];
    for(i=0;i<G->vexnum;i++)
    {
        arr[i]=0;
    }
    for(i = 0;i<G->vexnum;i++)
    {
        p = G->adjlist[i].firstarc;
        while(p!=NULL)
        {
            //根据有向图的结构
            //表头节点后面连接的表体的数据p->adjvex,出现一次就是作为入度一次
            //比如0后面有1,2,那么顶点1和2肯定都作为后驱一次,就有一个入度
            arr[p->adjvex]++;
            //指针移动到下一个表体
            p=p->nextarc;
        }

    }
    
    
    /*操蛋的输出格式!*/
    for(i=0;i<G->vexnum;i++){
        if(i!=G->vexnum-1)
            printf("%d ",arr[i]);
        else
            printf("%d",arr[i]);
    }

    printf("\n");
}

总结:其实这个题目对图的操作还是很简单的,主要是理解了图的邻接表的表示方法其实就是数组+链表的组成结构,剩下的无非就是对单链表的操作而已。

猜你喜欢

转载自blog.csdn.net/Xenoverse/article/details/83959757