邻接矩阵存储有向图

发布时间 2023-08-30 10:39:46作者: 正确选项

AI验证代码逻辑没有错误。

/*
    有向图的基本操作包括:
    
    1. 初始化图:创建一个空的图数据结构,并初始化图的顶点数和边数。
    
    2. 创建图
    
    3. 判断图是否为空 
    
    4. 添加顶点:向图中添加一个新的顶点。
    
    5. 添加边:在图中添加一条连接两个顶点的边。
    
    6. 删除顶点:从图中删除一个指定的顶点,同时删除与该顶点相关联的边。
    
    7. 删除边:从图中删除一条指定的边。
    
    8. 判断顶点是否存在:检查图中是否存在指定的顶点。
    
    9. 判断边是否存在:检查图中是否存在指定的边。
    
    10. 获取顶点的出度邻居顶点:获取指定顶点指向的顶点集合。
    
    11. 获取顶点的入度邻居顶点:获取指向指定顶点的顶点集合。
    
    12. 获取顶点的入度:计算指定顶点的入度,即与该顶点相连的边的数量。
    
    13. 获取顶点的出度:计算指定顶点的出度,即从该顶点出发的边的数量。
    
    14. 获取顶点的度:计算指定顶点的度,即入度和出度的总和。
    
    15. 打印邻接矩阵 

*/

#include <stdlib.h>
#include <stdio.h>

#define MaxVertexNum 20

typedef int VertexType; 
typedef int EdgeType;
typedef struct{
    VertexType Vex[MaxVertexNum];                //存储顶点 
    EdgeType Edge[MaxVertexNum][MaxVertexNum];    //存储边 
    int VexNum;                                    //顶点数 
    int EdgeNum;                                //边数 
}Graph;

//1.初始化图 
void InitGraph(Graph &G)
{
    int i,j;
    for(i=0;i<MaxVertexNum;i++)
    {
        G.Vex[i]=0;                            //顶点值初始化为0 
        for(j=0;j<MaxVertexNum;j++)            
            G.Edge[i][j]=0;                    //邻接矩阵中的元素初始化为0 
    }
    G.VexNum=0;                                //顶点个数初始化为0 
    G.EdgeNum=0;                            //边数初始化为0 
}

//2.创建图 
bool CreateGraph(Graph &G)
{
    int MaxNum,i,j;
    printf("图的顶点个数为:");
    scanf("%d",&MaxNum);
    if(MaxNum<=0)
        return false;
    G.VexNum=MaxNum;
    
    printf("输入顶点值:\n");
    for(i=0;i<G.VexNum;i++)
    {
        scanf("%d",&G.Vex[i]);    
    }
    
    printf("输入(0/1)到邻接矩阵:\n");
    int count=0;
    for(i=0;i<G.VexNum;i++)
    {
        for(j=0;j<G.VexNum;j++)
        {
            scanf("%d",&G.Edge[i][j]);
            if(G.Edge[i][j]==1)
                count++; 
        }
    }
    G.EdgeNum=count/2;
}

//3.判断图是否为空 
bool isValid(Graph G)
{
    //判断是否为空 
    if(G.VexNum<=0)
    {
        printf("图空\n");
        return false;
    }
    return true;
}

//4.添加顶点
bool AddVertex(Graph &G,VertexType ver)
{
    if(G.VexNum==MaxVertexNum-1)
        return false;
        
    for(int i=0;i<G.VexNum;i++)
        if(G.Vex[i]==ver)
            return false; 
            
    G.Vex[G.VexNum]=ver;
    G.VexNum++;
    
    for(int i=0;i<G.VexNum;i++)
    {
        G.Edge[G.VexNum-1][i]=0;
        G.Edge[i][G.VexNum-1]=0;
    }
    
    return true;
} 

//5.添加边
bool AddEdge(Graph &G,VertexType ver1,VertexType ver2)
{
    int v1=-1;
    int v2=-2;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Vex[i]==ver1)
            v1=i;
        if(G.Vex[i]==ver2)
            v2=i;
        if(v1>=0 && v2>=0)        //提前结束 
            break;    
    }
    if(v1<0 || v2<0)
        return false;
        
    G.Edge[v1][v2]=1;
    G.Edge[v2][v1]=1;
    G.EdgeNum++;
    
    return true;
} 

//6.删除顶点
bool DeleteVertex(Graph &G,VertexType ver)
{
    int v=-1;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Vex[i]==ver)
        {
            v=i;
            break;
        }
    }
    if(v<0)
        return false;
    
    for(int i=v;i<G.VexNum-1;i++)
    {
        for(int j=0;j<G.VexNum;j++)
        {
            G.Edge[i][j]=G.Edge[i+1][j];
            G.Edge[j][i]=G.Edge[j][i+1];
        }
    }    
    
    for(int i=v;i<G.VexNum-1;i++)
        G.Vex[i]=G.Vex[i+1];
    G.VexNum--;
    
    int count=0;
    for(int i=0;i<G.VexNum;i++)
        for(int j=0;j<G.VexNum;j++)
            if(G.Edge[i][j]==1 || G.Edge[j][i]==1)
                count++;
    G.EdgeNum=count/2;
    
    return true;
} 

//7.删除边(ver1指向ver2的边)
bool DeleteEdge(Graph &G,VertexType ver1,VertexType ver2)
{
    int v1=-1;
    int v2=-1;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Vex[i]==ver1)
            v1=i;
        if(G.Vex[i]==ver2)
            v2=i;
        if(v1>=0 && v2>=0)        //提前结束 
            break;    
    }    
    if(v1<0 || v2<0)
        return false;
        
    G.Edge[v1][v2]=0;
    G.EdgeNum--;
    
    return true;
} 

//8.判断顶点是否存在
bool ExistVertex(Graph G,VertexType ver)//传入的是顶点值,不是下标 
{
    for(int i=0;i<G.VexNum;i++)
        if(G.Vex[i]==ver)
            return true;        
    return false;
}

//9.判断边是否存在(ver1指向ver2的边) 
bool ExistEdge(Graph G,VertexType ver1,VertexType ver2)//传入的是顶点值,不是下标 
{
    int v1,v2;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Vex[i]==ver1)
            v1=i;
        if(G.Vex[i]==ver2)
            v2=i;    
        if(v1>=0 && v2>=0)        //提前结束 
            break;    
    } 
    
    if(G.Edge[v1][v2]==0)
        return false;
    return true;
}

//10.获取顶点的出度邻居顶点
bool GetInNeiborVertex(Graph G,VertexType ver)
{
    int v=-1;
    for(int i=0;i<G.VexNum;i++)
    {
         if(G.Vex[i]==ver)
         {
            v=i;
             break; 
        }
    }
    if(v==-1)
    {
        printf("顶点不存在\n");
        return false;
    }
    
    printf("%d的出度邻居顶点为:",ver]);
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Edge[v][i]==1)
            printf("%d ",G.Vex[i]);
    }
    
    return true;
} 

//11.获取顶点的入度邻居顶点
bool GetOutNeiborVertex(Graph G,VertexType ver)
{
    int v=-1;
    for(int i=0;i<G.VexNum;i++)
    {
         if(G.Vex[i]==ver)
         {
            v=i;
             break; 
        }
    }
    if(v==-1)
    {
        printf("顶点不存在\n");
        return false;
    }
    
    printf("%d的出度邻居顶点为:",ver]);
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Edge[i][v]==1)
            printf("%d ",G.Vex[i]);
    }
    
    return true;
} 

//12.求顶点的入度
int GetInDegree(Graph G,VertexType v)        //注意传入的是数组的下标 
{
    int v=-1;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Vex[i]==ver)
        {
            v=i;
            break;
        }
    }
    if(v<0)
        return 0;
    
    int degree=0;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Edge[v][i]==1)
            degree++; 
    }
    return degree;
}

//13.求顶点的出度
int GetOutDegree(Graph G,VertexType ver)
{
    int v=-1;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Vex[i]==ver)
        {
            v=i;
            break;
        }
    }
    if(v<0)
        return 0;
        
    int degree=0;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Edge[i][v]==1)
            degree++;    
    }    
    return degree;
}

//14.求顶点的度
int GetDegree(Graph G,VertexType ver)
{
    int v=-1;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Vex[i]==ver)
        {
            v=i;
            break;
        }
    }
    if(v<0)
        return 0;
    
    int degree=0;
    for(int i=0;i<G.VexNum;i++)
    {
        if(G.Edge[i][v]==1)
            degree++;
        if(G.Edge[v][i]==1)
            degree++;
    }
    return degree;
} 

//15.打印邻接矩阵 
void DisplayGraph(Graph G)
{
    int i,j;
    printf("顶点结点:\n");
    for(i=0;i<G.VexNum;i++)
    {
        printf("%d  ",G.Vex[i]);
    }
    printf("\n");
    printf("邻接矩阵:\n");
    for(i=0;i<G.VexNum;i++)
    {
        for(j=0;j<G.VexNum;j++)
        {
            printf("%d  ",G.Edge[i][j]);
            if(j==G.VexNum-1)
                printf("\n");
        }
    }
    printf("图的边数为:%d\n",G.EdgeNum);
}

/*int main()
{
    Graph G;
    InitGraph(G);
    CreateGraph(G);
    if(isValid(G)) 
        DisplayGraph(G);
    printf("顶点1的入度为%d\n",GetInDegree(G,0));
    printf("顶点1的出度为%d\n",GetOutDegree(G,0));
    printf("顶点1的度为%d\n",GetDegree(G,0));
    return 0;
}
*/