# 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;
}