图(十字链表)

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

# define VERTEXMAXNUM 10
# define WEIGHTMAXNUM 10
# define ALLGRAPHKINDNUM 3
# define GRAPHKINDNAMENUM 2

typedef enum{DG,DN} GraphKind;
typedef char VertexType;
typedef int Weight;
typedef char AllGraphKind[ALLGRAPHKINDNUM];
typedef char AllGraphKindName[GRAPHKINDNAMENUM];

typedef struct ArcNode *Arc;
struct ArcNode
{
    int headindex;//弧头的数组下标
    int tailindex;//弧尾的数组下标
    Arc headlink;//指向同一弧头的边
    Arc taillink;//指向同一弧尾的边
    Weight weight;//权值
};

typedef struct VexNode
{
    VertexType data;//用字母表示
    Arc firstin;//指向第一个以该顶点为弧尾的边
    Arc firstout;//指向第一个以该顶点为弧头的边
    int outcnt;//记录该顶点作为弧头的次数
}Vertex;

typedef struct GNode *Graph;
struct GNode
{
    GraphKind kind;//图的类型
    Vertex vexs[VERTEXMAXNUM];//顶点数组
    int vexnum;//顶点数量
    int arcnum;//边/弧数量
    int len_thisvexs;//当前顶点数组的长度
};

/*输入图的类型*/
bool Input_GraphKind(Graph graph)
{
    bool flag = true;
    
    AllGraphKindName inputGraphKind;//存放输入的图的类型
    printf("请输入图的类型:");
    scanf("%s",inputGraphKind);
    if(!strcmp(inputGraphKind,"DG"))
        graph->kind = DG;
    else if(!strcmp(inputGraphKind,"DN"))
        graph->kind = DN;
    else
    {
        flag = false;
        printf("无效数值,请重新输入:\n");
        
    }
    
    return flag;
}

/*输入顶点数量*/
bool Input_GraphVexNum(Graph graph)
{
    bool flag = true;
    
    int inputVexNum;
    printf("请输入顶点数量:");
    fflush(stdin); //清除缓存
    int ret = scanf("%d",&inputVexNum);
    if(ret && getchar() == '\n')//防止输入无效字符
    {
        if(inputVexNum > 0 && inputVexNum <= VERTEXMAXNUM)
            graph->vexnum = inputVexNum;    
        else if(inputVexNum <= 0)
        {
            flag = false;
            printf("顶点数量<=0,请重新输入:\n");
        }
        else
        {
            flag = false;
            printf("顶点数量>最大数值,请重新输入:\n");
         }
    }
    else
    {
        flag = false;
        printf("无效数值,请重新输入:\n");
    }
    
    return flag;
}

/*输入弧/边的数量*/
bool Input_GraphArcNum(Graph graph)
{
    bool flag = true;
    
    int inputArcNum;
    
       printf("请输入弧数量:");
    
    fflush(stdin); //清除缓存
    int ret = scanf("%d",&inputArcNum);
    if(ret && getchar() == '\n')//防止输入无效字符
    {
        if(inputArcNum >= 0 && inputArcNum <= graph->vexnum*(graph->vexnum - 1))
            graph->arcnum = inputArcNum;
        else if(inputArcNum < 0)
        {
            flag = false;
               printf("输入的弧数量<0,请重新输入:\n");
        }
        else
        {
            flag = false;
               printf("输入的弧数量>最大数值,请重新输入:\n");
        }
    }
    else
    {
        flag = false;
        printf("无效数值,请重新输入:\n");
    }

    return flag;
}

/*检查输入的顶点是否重复*/
bool Check_InputVexIsRecurring(Graph graph,VertexType inputVex)
{
    bool flag = false;
    
    for(int i=0;i<graph->len_thisvexs;i++)
    {
        if(inputVex == graph->vexs[i].data)
        {
            flag = true;
            break;
        }
    }
    
    return flag;
}

/*输入顶点*/
bool Input_GraphVex(Graph graph)
{
    graph->len_thisvexs = 0;
    
    bool flag = true;
    
    VertexType inputVex;
    
    for(int i=0;i<graph->vexnum;i++)
    {
        while(true)
        {   
            printf("请输入第%d个顶点:",(i+1));
            fflush(stdin); //清除缓存
            scanf("%c",&inputVex);
            if(!Check_InputVexIsRecurring(graph,inputVex))
                break;
            else
                printf("输入的顶点已存在,请重新输入:\n");
        }
            
        graph->vexs[i].data = inputVex;
        graph->vexs[i].firstin = NULL;
        graph->vexs[i].firstout = NULL;
        graph->vexs[i].outcnt = 0;
        
        graph->len_thisvexs++;    
    }
    
    return flag;
}

/*初始化图*/
void Init_Graph(Graph graph)
{
    printf("欢迎使用!\n");
    
    /*输入图的类型*/
    while(true)
    {
        if(Input_GraphKind(graph))
            break;
    }
    
    /*输入顶点数量*/
    while(true)
    {
        if(Input_GraphVexNum(graph))
            break;
    }
    
    /*输入弧/边的数量*/
    while(true)
    {
        if(Input_GraphArcNum(graph))
            break;
    }
     
    /*输入顶点*/
    while(true)
    {
        if(Input_GraphVex(graph))
        break;
    }
}

/*展示图的横、逆邻接表结构*/
void Show_AllAdjacencyList(Graph graph)
{
    /*展示图的横、逆邻接表结构*/
    printf("该图的横邻接表结构是:\n");
    for(int i=0;i<graph->vexnum;i++)
    {
        printf("%c ",graph->vexs[i].data);//展示图中每个顶点
        
        Arc arcTemp = graph->vexs[i].firstout;//创建一个中间容器存放边/弧
        while(arcTemp)
        {
            printf("-> ");
            printf("%c ",graph->vexs[arcTemp->tailindex].data);
            arcTemp = arcTemp->headlink;
        }
        
        printf("\n");//每个顶点隔开
    }
    
    /*展示图的逆邻接表结构*/
    printf("该图的逆邻接表结构是:\n");
    for(int i=0;i<graph->vexnum;i++)
    {
        printf("%c ",graph->vexs[i].data);//展示图中每个顶点
        
        Arc arcTemp = graph->vexs[i].firstin;//创建一个中间容器存放边/弧
        while(arcTemp)
        {
            printf("-> ");
            printf("%c ",graph->vexs[arcTemp->headindex].data);
            arcTemp = arcTemp->taillink;
        }
        
        printf("\n");//每个顶点隔开
    }
}

/*输出图*/
void Show_Graph(Graph graph)
{
    printf("\n");//与输入的数据隔开
    
    /*输出图的类型*/
    AllGraphKind thisGraphKind[ALLGRAPHKINDNUM]={"DG","DN"};
    printf("该图的类型是:%s\n",thisGraphKind[graph->kind]);
    
    /*输出图的顶点数量*/
    printf("该图有%d个顶点\n",graph->vexnum);
    
    /*输出图的弧/边数量*/
    if(graph->kind == DN || graph->kind == DG)
        printf("该图有%d个弧\n",graph->arcnum);
    else
        printf("该图有%d个边\n",graph->arcnum);
    
    /*输出图的顶点*/
    for(int i=0;i<graph->vexnum;i++)
        printf("第%d个顶点:%c\n",i+1,graph->vexs[i].data);
    
    /*输出图的当前顶点数量*/
    printf("该图当前有%d个顶点\n",graph->len_thisvexs);
    
    /*输出图的权值*/
    if(graph->kind == DN )
    {
        for(int i=0;i<graph->arcnum;i++)
        {
            Arc arcTemp = graph->vexs[i].firstout;
            while(arcTemp)
            {
                printf("%c -> %c的权值:%d\n",
                graph->vexs[i].data,graph->vexs[arcTemp->tailindex].data,arcTemp->weight);                    
                arcTemp = arcTemp->headlink;
            }
        }
    }
    
    /*展示图的横、逆邻接表结构*/
    Show_AllAdjacencyList(graph);
}

/*查询顶点在图中的位置(即顶点数组的下标)*/
int SingleVexIndex_Graph(VertexType vex,Graph graph)
{
    int index = -1;
    for(int i=0;i<graph->vexnum;i++)
    {
        if(vex == graph->vexs[i].data)
            index = i;
    }
    return index;
}

/*创建弧/边时,检查输入的两个顶点是否在图中(即顶点数组中)*/
bool Check_InputVexBelongsToGraph(Graph graph,int index)
{
    bool flag = true;
    
    if(index == -1)
    {
        flag = false;
        printf("输入的顶点不在图中,请重新输入:\n");
    }
    
    return flag;
}

/*检查输入的边/弧的第一个顶点是否重复超出规定次数*/
bool Check_InputFirstVexOfArcIsRecurring(Graph graph,int V1_Index)
{
    bool flag = false;
    
    graph->vexs[V1_Index].outcnt++;
    if(graph->vexs[V1_Index].outcnt >= graph->vexnum)
    {
        flag = true;
        printf("输入的顶点已重复,请重新输入:\n");
    }
    
    return flag;
}

/*检查输入的边/弧是否重复*/
bool Check_InputArcIsRecurring(Graph graph,int V1_Index,int V2_Index)
{
    bool flag = false;
    
    Arc arcTemp = graph->vexs[V1_Index].firstout;//中间容器存放每个顶点的每一条边
    while(arcTemp)
    {
        if(arcTemp->tailindex == V2_Index)
        {
            flag = true;
            break;
        }
        
        arcTemp = arcTemp->headlink;
    }
     
    return flag;
}

/*竖逆*/
void Create_InverseAdjacency(Graph graph)
{
    for(int i=0;i<graph->vexnum;i++)
    {
        Arc arcTemp = graph->vexs[i].firstout;
        while(arcTemp)
        {
            arcTemp->taillink = graph->vexs[arcTemp->tailindex].firstin;
            graph->vexs[arcTemp->tailindex].firstin = arcTemp;
            arcTemp = arcTemp->headlink;
        }
    }
}

/*构造有向图的横邻部分*/
void CreateAdjacency_DG(Graph graph)
{
    VertexType V1,V2;//一条弧/边需要两个顶点 V1:弧头 V2:弧尾
    int V1_Index,V2_Index;//两个顶点的位置
    
    for(int i=0;i<graph->arcnum;i++)
    {
        /*输入两个顶点*/
        while(true)
        {
            printf("请输入第%d条弧的第1个顶点V1:",i+1);
            fflush(stdin); //清除缓存
            scanf("%c",&V1);
                        
            /*查询V1的位置*/
            V1_Index = SingleVexIndex_Graph(V1,graph);
            if(Check_InputVexBelongsToGraph(graph,V1_Index))
            {
                if(!Check_InputFirstVexOfArcIsRecurring(graph,V1_Index))
                    break;
            }                
        }
                    
        while(true)
        {
            printf("请输入第%d条弧的第2个顶点V2:",i+1);
            fflush(stdin); //清除缓存
            scanf("%c",&V2);
                        
            /*查询V2的位置*/
            V2_Index = SingleVexIndex_Graph(V2,graph);
            if(Check_InputVexBelongsToGraph(graph,V2_Index))
            {
                if(!Check_InputArcIsRecurring(graph,V1_Index,V2_Index))
                    break;
                else
                   printf("输入的弧已存在,请重新输入:\n");
            }                                            
        }
                
        /*创建V1 -> V2的弧结点*/             
        Arc V1_arc_V2 = (Arc)malloc(sizeof(ArcNode));
        
        /*横邻*/
        V1_arc_V2->headindex = V1_Index;
        V1_arc_V2->tailindex = V2_Index;
        V1_arc_V2->headlink = graph->vexs[V1_Index].firstout;
        graph->vexs[V1_Index].firstout = V1_arc_V2;        
        
        /*权值*/
        V1_arc_V2->weight = -1;
    }
}

/*构造有向图*/
void Create_DG(Graph graph)
{
    CreateAdjacency_DG(graph);
    Create_InverseAdjacency(graph);
}

/*输入权值*/
bool Input_Weight(Arc arc,Weight weight)
{
    bool flag = true;
    
    if(weight >= 0 && weight <= WEIGHTMAXNUM)
        arc->weight = weight;    
    else if(weight < 0)
    {
        flag = false;
        printf("输入的权值<0,请重新输入:\n");
    }
    else
    {
        flag = false;
        printf("输入的权值>最大数值,请重新输入:\n");
    }
    return flag;
}

/*构造有向网的横邻部分*/
void CreateAdjacency_DN(Graph graph)
{
    VertexType V1,V2;//一条弧/边需要两个顶点 V1:弧头 V2:弧尾
    int V1_Index,V2_Index;//两个顶点的位置
    Weight weight;//每一条边的权值
    
    for(int i=0;i<graph->arcnum;i++)
    {
        /*输入两个顶点*/
        while(true)
        {        
            printf("请输入第%d条弧的第1个顶点V1:",i+1);
            fflush(stdin); //清除缓存
            scanf("%c",&V1);
            
            /*查询V1的位置*/
            V1_Index = SingleVexIndex_Graph(V1,graph);
            if(Check_InputVexBelongsToGraph(graph,V1_Index))
            {
                if(!Check_InputFirstVexOfArcIsRecurring(graph,V1_Index))
                    break;
            }
        }
        
        while(true)
        {        
            printf("请输入第%d条弧的第2个顶点V2:",i+1);
            fflush(stdin); //清除缓存
            scanf("%c",&V2);
            
            /*查询V2的位置*/
            V2_Index = SingleVexIndex_Graph(V2,graph);
            if(Check_InputVexBelongsToGraph(graph,V2_Index))
            {
                if(!Check_InputArcIsRecurring(graph,V1_Index,V2_Index))
                    break;
                else
                    printf("输入的弧已存在,请重新输入:\n");
            }
        }
        
        /*创建V1 -> V2的弧结点*/
        Arc V1_arc_V2 = (Arc)malloc(sizeof(ArcNode));
        while(true)//输入权值
        {
            printf("请输入第%d条弧的权值:",i+1);
            fflush(stdin);//去除回车干扰
            int ret = scanf("%d",&weight);
            if(ret && getchar()=='\n')
            {
                if(Input_Weight(V1_arc_V2,weight))
                    break;
            }
            else
                printf("无效数值,请重新输入:\n");                
        }
        V1_arc_V2->headindex = V1_Index;
        V1_arc_V2->tailindex = V2_Index;
        V1_arc_V2->headlink = graph->vexs[V1_Index].firstout;
        graph->vexs[V1_Index].firstout = V1_arc_V2;
    }
}

/*构造有向网*/
void Create_DN(Graph graph)
{
    CreateAdjacency_DN(graph);
    Create_InverseAdjacency(graph);
}

/*构造图*/
void Create_Graph(Graph graph)
{
    /*根据图的类型构造图*/
    switch(graph->kind)
    {
        case DG:Create_DG(graph);
                break;
        
        case DN:Create_DN(graph);
                break;
    }
}

/*求图/网的出度*/
int Compute_OutDegree(VertexType vex,Graph graph)
{
    int outDegree;
        
    int vexIndex = SingleVexIndex_Graph(vex,graph);
    if(Check_InputVexBelongsToGraph(graph,vexIndex))
    {
        outDegree = 0;
        Arc arcTemp = graph->vexs[vexIndex].firstout;
        while(arcTemp)
        {
            outDegree++;
            arcTemp = arcTemp->headlink;
        }
    }
    else
        outDegree = -1;
        
    return outDegree;
}

/*查询图/网的出度*/
void OutDegree_Graph(VertexType vex,Graph graph)
{
    while(true)
    {
        printf("请输入需要查询出度的顶点:");
        fflush(stdin);
        scanf("%c",&vex);
        int outDegree = Compute_OutDegree(vex,graph);    
        if(outDegree != -1)
        {
            printf("顶点%c的出度:%d\n",vex,outDegree);
            break;
        }     
    }
}

/*求图/网的入度*/
int Compute_InDegree(VertexType vex,Graph graph)
{
    int inDegree;
    
    int vexIndex = SingleVexIndex_Graph(vex,graph);
    if(Check_InputVexBelongsToGraph(graph,vexIndex))
    {
        inDegree = 0;
        Arc arcTemp = graph->vexs[vexIndex].firstin;
        while(arcTemp)
        {
            inDegree++;
            arcTemp = arcTemp->taillink;
        }
    }
    else
        inDegree = -1;
        
    return inDegree;
}

/*查询图/网的入度*/
void InDegree_Graph(VertexType vex,Graph graph)
{
    while(true)
    {
        printf("请输入需要查询入度的顶点:");
        fflush(stdin);
        scanf("%c",&vex);
        int inDegree = Compute_InDegree(vex,graph);    
        if(inDegree != -1)
        {
            printf("顶点%c的入度:%d\n",vex,inDegree);
            break;
        }     
    }
}

/*求图/网的度*/
int Compute_Degree(VertexType vex,Graph graph)
{
    int outDegree = Compute_OutDegree(vex,graph);
    int inDegree = Compute_InDegree(vex,graph);
    int degree = outDegree + inDegree;
    return degree;
}

/*查询图/网的度*/
void Degree_Graph(VertexType vex,Graph graph)
{
    while(true)
    {
        printf("请输入需要查询度的顶点:");
        fflush(stdin);
        scanf("%c",&vex);
        int degree = Compute_Degree(vex,graph);    
        if(degree != -1)
        {
            printf("顶点%c的度:%d\n",vex,degree);
            break;
        }     
    }
}

/*查询图/网的出度、入度、度*/
void AllDegree_Graph(VertexType vex,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否有需要查询出度、入度、度的顶点:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            /*出度*/
            while(true)
            {
                printf("请输入是否有需要查询出度的顶点:");
                fflush(stdin);
                scanf("%s",opt);
                if(!strcmp(opt,"是"))
                    OutDegree_Graph(vex,graph);
                else if(!strcmp(opt,"否"))
                    break;
                 else
                    printf("无效数值,请重新输入:\n");
            }
            
            /*入度*/
            while(true)
            {
                printf("请输入是否有需要查询入度的顶点:");
                fflush(stdin);
                scanf("%s",opt);
                if(!strcmp(opt,"是"))
                    InDegree_Graph(vex,graph);
                else if(!strcmp(opt,"否"))
                    break;
                 else
                    printf("无效数值,请重新输入:\n");
            }
            
            /*度*/
            while(true)
            {
                printf("请输入是否有需要查询度的顶点:");
                fflush(stdin);
                scanf("%s",opt);
                if(!strcmp(opt,"是"))
                    Degree_Graph(vex,graph);
                else if(!strcmp(opt,"否"))
                    break;
                 else
                    printf("无效数值,请重新输入:\n");
            }
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询顶点在的图/网中的位置*/
void AllIndex_Graph(VertexType vex,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    int index;
    
    while(true)
    {
        printf("请输入是否有需要查询位置的顶点:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            while(true)
            {
                printf("请输入顶点:");
                fflush(stdin);
                scanf("%c",&vex);
                index = SingleVexIndex_Graph(vex,graph);
                if(Check_InputVexBelongsToGraph(graph,index))
                {
                    if(graph->kind == DG)
                        printf("顶点%c是该图的第%d个顶点\n",vex,index+1);
                    else
                        printf("顶点%c是该网的第%d个顶点\n",vex,index+1);
                        
                    break;
                }
            }
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询第i个顶点*/
void AllVex_Graph(int index,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    VertexType vex;
    
    while(true)
    {
        printf("请输入是否有需要通过位置查询的顶点:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            while(true)
            {
                printf("请输入位置(数字):");
                fflush(stdin);
                int ret = scanf("%d",&index);
                if(ret && getchar()=='\n')
                {
                    if(index > 0 && index <= graph->vexnum)
                    {
                        if(graph->kind == DG)
                         printf("该图的第%d个顶点是%c\n",index,graph->vexs[index-1].data);
                        else
                         printf("该网的第%d个顶点是%c\n",index,graph->vexs[index-1].data);
                        
                        break;
                    }
                    else if(index <= 0)
                        printf("输入的位置<=0,请重新输入:\n");
                    else
                        printf("输入的位置>已有的数量,请重新输入:\n");
                }
                else
                    printf("无效数值,请重新输入:\n");
            }
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询边是否存在*/
bool Check_InputArcBelongsToGraph(int v1_index,int v2_index,Graph graph)
{
    bool flag = true;
    
    if(!Check_InputArcIsRecurring(graph,v1_index,v2_index))
        flag = false;
    
    return flag;
}

/*查询权值*/
void AllWeight_Graph(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    VertexType v1,v2;
    int v1_index,v2_index;
    
    while(true)
    {
        printf("请输入是否有需要查询权值的边:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            while(true)
            {
                while(true)
                {
                    printf("请输入该边的第一个顶点:");
                    fflush(stdin);
                    scanf("%c",&v1);
                    v1_index = SingleVexIndex_Graph(v1,graph);
                    if(Check_InputVexBelongsToGraph(graph,v1_index))
                        break;
                }
                
                while(true)
                {
                    printf("请输入该边的第二个顶点:");
                    fflush(stdin);
                    scanf("%c",&v2);
                    v2_index = SingleVexIndex_Graph(v2,graph);
                    if(Check_InputVexBelongsToGraph(graph,v2_index))
                        break;
                }
                
                if(Check_InputArcBelongsToGraph(v1_index,v2_index,graph))
                {
                    Arc arcTemp = graph->vexs[v1_index].firstout;
                    while(arcTemp)
                    {
                        if(arcTemp->tailindex == v2_index)
                        {
                            printf("%c -> %c的权值:%d\n",v1,v2,arcTemp->weight);
                            break;
                           }
                                           
                        arcTemp = arcTemp->headlink;
                    }
                    
                    break;                    
                }
                else
                     printf("输入的边不存在,请重新输入:\n");                
            }
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询图的类型*/
void Check_GraphKind(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要查询图的类型:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            AllGraphKind thisGraphKind[ALLGRAPHKINDNUM]={"DG","DN"};
            printf("该图的类型是:%s\n",thisGraphKind[graph->kind]);
            break;
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询图的顶点数量*/
void Check_VexNum(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要查询图的顶点数量:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            printf("该图的顶点数量:%d\n",graph->vexnum);
            break;
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询图的弧数量*/
void Check_ArcNum(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要查询图的弧数量:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            printf("该图的弧数量:%d\n",graph->arcnum);
            break;
        }            
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询图现有的顶点*/
void Check_ThisVexs(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要查询图当前已有的顶点:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            printf("该图当前已有的顶点:");
            
            for(int i=0;i<graph->len_thisvexs;i++)
                printf("%c ",graph->vexs[i].data);
            printf("\n");
                
            break;
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*查询图的基本信息*/
void Check_GraphBaseInfo(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要查询图的基本信息:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            Check_GraphKind(graph);
            Check_VexNum(graph);
            Check_ArcNum(graph);
            Check_ThisVexs(graph);
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*删除第i个顶点的横 */
void Delete_HeadVex(int index,Graph graph)
{
    Arc arcOutTemp = graph->vexs[index].firstout;
    while(arcOutTemp)
    {
        int cnt=0;
        Arc arcOutTempBack = arcOutTemp->headlink;
        Arc arcTempout = arcOutTemp;
                        
        Arc arcTempin = graph->vexs[arcTempout->tailindex].firstin;
        Arc arcTempinP = arcTempin;
        while(arcTempin)  
        {
            cnt++;                        
            if(arcTempin->headindex == index)
                break;
            arcTempinP = arcTempin;
            arcTempin = arcTempin->taillink;
        }
                        
        if(cnt==1)
            graph->vexs[arcTempout->tailindex].firstin = arcTempin->taillink;
        else
            arcTempinP->taillink = arcTempin->taillink;
                        
        graph->vexs[index].firstout = arcOutTempBack;
        arcOutTemp = arcOutTempBack;
        free(arcTempout);        
    }
}

/*删除第i个顶点的逆*/
void Delete_TailVex(int index,Graph graph)
{
    Arc arcInTemp = graph->vexs[index].firstin;    
    while(arcInTemp)
    {
        int cnt = 0;
        Arc arcInTempBack = arcInTemp->taillink;
        Arc arcTempin = arcInTemp;
                        
        Arc arcTempout = graph->vexs[arcTempin->headindex].firstout;
        Arc arcTempoutP = arcTempout;
        while(arcTempout)
        {
            cnt++;
            if(arcTempout->tailindex == index)
                break;
                arcTempoutP = arcTempout;
                arcTempout = arcTempout->headlink;
        }
                           
        if(cnt==1)
            graph->vexs[arcTempin->headindex].firstout = arcTempout->headlink;
        else
            arcTempoutP->headlink = arcTempout->headlink;
                        
        graph->vexs[index].firstin = arcInTempBack;
        arcInTemp = arcInTempBack;
        free(arcTempin);    
    }
}

/*删除第i个顶点*/
void Delete_Vex(VertexType vex,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要删除顶点:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            printf("请输入需要删除?顶点:");
            fflush(stdin);
            scanf("%c",&vex);
            if(Check_InputVexIsRecurring(graph,vex))
            {
                int index = SingleVexIndex_Graph(vex,graph);
                
                Delete_HeadVex(index,graph);
                Delete_TailVex(index,graph);                            
                    
                if(index != graph->vexnum)
                    for(int i=index;i<=graph->vexnum - index+1;i++)
                        graph->vexs[i] = graph->vexs[i+1];
                    
                graph->vexnum--;
                      
                for(int i=0;i<graph->vexnum;i++)
                {
                    Arc arcTemp = graph->vexs[i].firstout;
                    while(arcTemp)
                    {    
                        if(arcTemp->headindex > index)                        
                            arcTemp->headindex = arcTemp->headindex -1;
                        if(arcTemp->tailindex > index)
                            arcTemp->tailindex = arcTemp->tailindex -1;
                        arcTemp = arcTemp->headlink;
                    }    
                }    
            }
            else
                printf("输入的顶点不存在,请重新输入:\n");
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*增加n个顶点*/
void Add_Vex(int n,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    VertexType vex;
    int thisNum = graph->vexnum;
    
    while(true)
    {
        printf("请输入是否需要增加顶点:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {        
            while(true)
            {   
                printf("请输入需要增加?个顶点:");
                fflush(stdin);
                int ret = scanf("%d",&n);
                if(ret && getchar()=='\n')
                {
                    if(graph->vexnum + n > VERTEXMAXNUM)
                        printf("顶点数量>最大数值,请重新输入:\n");
                    else if(n <= 0)
                        printf("需增加的数量<=0,请重新输入:\n");
                    else
                        break;
                }    
                else
                    printf("无效数值,请重新输入:\n");
            }     
            graph->vexnum += n;
                
            for(int i=thisNum;i<n;i++)
            {
                scanf("%c",&vex);
                while(true)
                {
                    if(!Check_InputVexIsRecurring(graph,vex))
                    {
                        graph->vexs[i].data = vex;
                        break;
                    }
                    else
                        printf("输入的顶点已存在,请重新输入:\n");
                }                 
                graph->vexs[i].firstin = NULL;
                graph->vexs[i].firstout = NULL;
                graph->vexs[i].outcnt = 0;
            }    
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*删除横向的弧*/
void Delete_HeadArc(int vex1Index,int vex2Index,Graph graph)
{
    int cnt1=0;
    Arc arcTempout = graph->vexs[vex1Index].firstout;
    Arc arcTempoutP = arcTempout;
    
    while(true)
    {
        cnt1++;
        if(arcTempout->tailindex == vex2Index)
            break;
            arcTempoutP = arcTempout;
            arcTempout = arcTempout->headlink;
        }
            
        if(cnt1==1)
            graph->vexs[vex1Index].firstout = arcTempout->headlink;
        else
            arcTempoutP->headlink = arcTempout->headlink;
}

/*删除逆向的弧*/
void Delete_TailArc(int vex1Index,int vex2Index,Graph graph)
{
    int cnt2=0;
    Arc arcTempin = graph->vexs[vex2Index].firstin;
    Arc arcTempinP = arcTempin;
    
    while(true)
    {
        cnt2++;
        if(arcTempin->headindex == vex1Index)
            break;
            arcTempinP = arcTempin;
            arcTempin = arcTempin->taillink;
        }
            
        if(cnt2==1)
            graph->vexs[vex2Index].firstin = arcTempin->taillink;
        else
            arcTempinP->taillink = arcTempin->taillink;

        free(arcTempin);
}

/*删除弧v->w*/
void Delete_Arc(VertexType vex1,VertexType vex2,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    int vex1Index,vex2Index;
    
    while(true)
    {
        printf("请输入是否有需要删除的弧:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            while(true)
            {
                while(true)
                {
                    printf("请输入需要删除的弧的第一个顶点:");
                    fflush(stdin);
                    scanf("%c",&vex1);
                    if(Check_InputVexIsRecurring(graph,vex1))
                    {
                        vex1Index = SingleVexIndex_Graph(vex1,graph);
                        break;
                    }    
                    else
                        printf("输入的顶点不存在,请重新输入:\n");                
                }
            
                while(true)
                {
                    printf("请输入需要删除的弧的第二个顶点:");
                    fflush(stdin);
                    scanf("%c",&vex2);
                    if(Check_InputVexIsRecurring(graph,vex2))
                    {
                        vex2Index = SingleVexIndex_Graph(vex2,graph);
                        break;
                    }
                    else
                        printf("输入的顶点不存在,请重新输入:\n");    
                }
                
                if(Check_InputArcIsRecurring(graph,vex1Index,vex2Index))
                    break;
                else
                    printf("输入的弧不存在,请重新输入:\n");
            }
                        
            Delete_HeadArc(vex1Index,vex2Index,graph);                        
            Delete_TailArc(vex1Index,vex2Index,graph);
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*增加弧的横*/
void Add_HeadArc(int vex1Index,Arc newArc,Graph graph)
{
    newArc->headindex = vex1Index;
    newArc->headlink = graph->vexs[vex1Index].firstout;
    graph->vexs[vex1Index].firstout = newArc;
}

/*增加弧的逆*/
void Add_TailArc(int vex2Index,Arc newArc,Graph graph)
{
    newArc->tailindex = vex2Index;
    newArc->taillink = graph->vexs[vex2Index].firstin;
    graph->vexs[vex2Index].firstin = newArc;
}

/*增加n条弧*/
void Add_Arc(int n,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    VertexType vex1,vex2;
    int vex1Index,vex2Index;
    
    while(true)
    {
        printf("请输入是否需要增加弧:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {        
            while(true)
            {
                printf("请输入需要增加?个弧:");
                fflush(stdin);
                int ret = scanf("%d",&n);
                if(ret && getchar()=='\n')
                {    
                    if(graph->arcnum + n > graph->vexnum*(graph->vexnum - 1))
                        printf("弧数量>最大数值,请重新输入:\n");
                    else if(n <= 0)
                        printf("需增加的数量<=0,请重新输入:\n");
                    else
                        break;            
                }    
                else
                    printf("无效数值,请重新输入:\n");
            }
            graph->arcnum += n;
            
            for(int i=0;i<n;i++)
            {
                while(true)
                {
                    while(true)
                    {
                        printf("请输入需要增加的第%d条弧的第一个顶点:",i+1);
                        fflush(stdin);
                        scanf("%c",&vex1);
                        if(Check_InputVexIsRecurring(graph,vex1))
                        {
                            vex1Index = SingleVexIndex_Graph(vex1,graph);
                            break;
                        }
                        else
                            printf("输入的顶点不存在,请重新输入:\n");                                        
                    }
            
                    while(true)
                    {
                        printf("请输入需要增加的第%d条弧的第二个顶点:",i+1);
                        fflush(stdin);
                        scanf("%c",&vex2);
                        if(Check_InputVexIsRecurring(graph,vex2))
                        {
                            vex2Index = SingleVexIndex_Graph(vex2,graph);
                            break;
                        }
                        else
                            printf("输入的顶点不存在,请重新输入:\n");    
                    }
                
                    if(!Check_InputArcIsRecurring(graph,vex1Index,vex2Index))
                        break;
                    else
                        printf("输入的弧已存在,请重新输入:\n");
                }
                            
                Arc newArc = (Arc)malloc(sizeof(ArcNode));            
                if(graph->kind == DN)
                {
                    Weight weight;
                    while(true)
                    {
                        printf("请输入需要增加的第%d条弧的权值:",i+1);
                        fflush(stdin);
                        int ret = scanf("%d",&weight);
                        if(ret && getchar()=='\n')
                        {
                            if(Input_Weight(newArc,weight))
                                break;
                        }
                        else
                            printf("无效数值,请重新输入:\n");
                    }
                    newArc->weight = weight;
                }
                else
                    newArc->weight = -1;
                    
                Add_HeadArc(vex1Index,newArc,graph);
                Add_TailArc(vex2Index,newArc,graph);
            }
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*修改单个弧的权值*/
void Change_SingleWeight(Weight weight,Arc arcTemp,Graph graph)
{
    while(true)
    {
        printf("请输入需要将该弧的权值修改为:");
        fflush(stdin);
        int ret = scanf("%d",&weight);
        if(ret && getchar()=='\n')
        {
            if(Input_Weight(arcTemp,weight))
                break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*修改弧的权值*/
void Change_Weight(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    Weight weight;
    VertexType vex1,vex2;
    int vex1Index,vex2Index;
    
    while(true)
    {
        printf("请输入是否需要修改弧的权值:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            while(true)
            {
                while(true)
                {
                    printf("请输入需要修改的弧的第一个顶点:");
                    fflush(stdin);
                    scanf("%c",&vex1);
                    if(Check_InputVexIsRecurring(graph,vex1))
                    {
                        vex1Index = SingleVexIndex_Graph(vex1,graph);
                        break;  
                    }   
                    else
                        printf("输入的顶点不存在,请重新输入:\n");    
                }
                
                while(true)
                {
                    printf("请输入需要修改的弧的第二个顶点:");
                    fflush(stdin);
                    scanf("%c",&vex2);
                    if(Check_InputVexIsRecurring(graph,vex2))
                    {
                        vex2Index = SingleVexIndex_Graph(vex2,graph);
                        break;  
                    }   
                    else
                        printf("输入的顶点不存在,请重新输入:\n");    
                }
                
                if(!Check_InputArcIsRecurring(graph,vex1Index,vex2Index))
                    break;
                else
                    printf("输入的弧已存在,请重新输入:\n");
            }
            
            Arc arcTemp = graph->vexs[vex1Index].firstout;
            while(arcTemp)
            {
                if(arcTemp->tailindex == vex2Index)
                    break;
                arcTemp = arcTemp->headlink;
            }
            
            Change_SingleWeight(weight,arcTemp,graph);            
            arcTemp->weight = weight;
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*修改DG的类型*/
void Change_DGKind(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    Weight weight;
    
    while(true)
    {
        printf("请输入是否需要修改图的类型:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            for(int i=0;i<graph->vexnum;i++)
            {
                Arc arcTemp = graph->vexs[i].firstout;
                
                while(arcTemp)
                {
                    printf("%c -> %c\n",
                    graph->vexs[i].data,graph->vexs[arcTemp->tailindex].data);
                    
                    Change_SingleWeight(weight,arcTemp,graph);    
                    arcTemp = arcTemp->headlink;
                }
            }
            
            graph->kind = DN;
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*修改DN的类型*/
void Change_DNKind(Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要修改图的类型:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            for(int i=0;i<graph->vexnum;i++)
            {
                Arc arcTemp = graph->vexs[i].firstout;
                while(arcTemp)
                {
                    arcTemp->weight = -1;
                    arcTemp = arcTemp->headlink;
                }
            }
            
            graph->kind = DG;
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

/*修改图的类型*/
void Change_Kind(Graph graph)
{
    if(graph->kind == DG)
        Change_DGKind(graph);
    else
        Change_DNKind(graph);
}

/*图的增、删、改*/
void AllOperation_Graph(VertexType vex,VertexType vex1,VertexType vex2,int n,Graph graph)
{
    printf("\n");
    printf("(需要:是;不需要:否)\n");
    
    char opt[3];
    
    while(true)
    {
        printf("请输入是否需要修改图:");
        
        fflush(stdin);
        scanf("%s",opt);
        
        if(!strcmp(opt,"是"))
        {
            Delete_Vex(vex,graph);
            Delete_Arc(vex1,vex2,graph);
            Add_Vex(n,graph);
            Add_Arc(n,graph);
            Change_Kind(graph);
            if(graph->kind == DN)
            Change_Weight(graph);
            Show_AllAdjacencyList(graph);
        }
        else if(!strcmp(opt,"否"))
        {
            printf("已退出,谢谢使用!\n");
            break;
        }
        else
            printf("无效数值,请重新输入:\n");
    }
}

int main()
{
    VertexType vex,vex1,vex2;
    int index,n;
    Graph graph = (Graph)malloc(sizeof(GNode));
    
    Init_Graph(graph);
    Create_Graph(graph);
    Show_Graph(graph);
    
    AllOperation_Graph(vex,vex1,vex2,n,graph);
        
    Check_GraphBaseInfo(graph);
    AllVex_Graph(index,graph);
    AllIndex_Graph(vex,graph);
    AllDegree_Graph(vex,graph);    
    if(graph->kind == DN)
        AllWeight_Graph(graph);
        
    free(graph);
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值