有向图的创建,插入删除顶点,插入删除弧,打印邻接矩阵和邻接表,查看顶点下标。
注:先分结构介绍,最后是完整代码和运行结果。
弧结点↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
typedef struct ArcNode
{
int AdjVertex;//邻接点下标
struct ArcNode *Next;
}ArcNode;
顶点域↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
typedef struct VertexNode
{
char Vertex;//顶点信息
ArcNode *FirstArc;
}VertexNode[MAXIMUM];
图结构↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
typedef struct Graph//有向图
{
VertexNode AdjList;//邻接表
int AdjMatrix[MAXIMUM][MAXIMUM];//邻接矩阵
int AmountofVertex;//顶点数
int AmountofArc;//边数
}Graph;
图的创建↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
int CreateGraph(Graph *G)//创建有向图
{
int i,j;
if(G==NULL)
{
printf("创建有向图失败!\n");//图创建失败
return ERROR;
}
else
printf("成功创建有向图\n");//图创建成功
G->AmountofArc=0;//0条边
G->AmountofVertex=0;//0个顶点
for(i=0;i<MAXIMUM;i++)
{
G->AdjList[i].FirstArc=NULL;//所有顶点集指向NULL
G->AdjList[i].Vertex='0';//所有顶点赋值为字符0
}
printf("\n");
return CORRECT;
}
单个顶点插入↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
int InsertVertex(Graph *G)//插入顶点
{
int k;
char vertex;
ArcNode *p;
printf("请输入要插入顶点的信息(一个字母)\n");//插入顶点
scanf("%c",&vertex);
getchar();
for(k=0;k<MAXIMUM;k++)
if(G->AdjList[k].Vertex=='0')
{
G->AdjList[k].Vertex=vertex;
G->AmountofVertex++;//顶点数加一
printf("\n");
return CORRECT;
}
printf("顶点数组集已满!插入失败!\n");//数组元素满
printf("\n");
return ERROR;
}
删除单个顶点及其相关弧↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
int DeleteVertex(Graph *G)//删除顶点(同时删除所有该顶点相关的弧)
{
int i,j,k;
ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱
printf("删除顶点vi,以及与v相关的所有弧,请依次输入顶点vi下标\n");
scanf("%d",&i);
getchar();
G->AdjList[i].Vertex='0';//删除顶点信息
G->AmountofVertex--;//顶点数减一
p=G->AdjList[i].FirstArc;
G->AdjList[i].FirstArc=NULL;
while(p) //删除出度的弧
{
del=p;
p=p->Next;
free(del);
G->AmountofArc--;//弧数量减一
}
for(k=0;k<=G->AmountofVertex;k++)//删除入度的弧
{
p=G->AdjList[k].FirstArc;
while(p)
{
if(p->AdjVertex==i)
{
if(p==G->AdjList[k].FirstArc)//被删除弧结点为第一个结点
{
del=p;
p=p->Next;
G->AdjList[k].FirstArc=p;
pre=NULL;
free(del);
G->AmountofArc--;//弧数量减一
break;
}
else
{
del=p;
p=p->Next;
pre->Next=p;
free(del);
G->AmountofArc--;//弧数量减一
break;
}
}
pre=p;
p=p->Next;
}
}
printf("\n\n");
return CORRECT;
}
插入弧↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
int InsertArc(Graph *G)
{
int i,j;
ArcNode *p,*Insert;
printf("插入弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
scanf("%d %d",&i,&j);
getchar();
if(G->AdjList[i].Vertex=='0'||G->AdjList[j].Vertex=='0')//不存在顶点vi或vj,插入失败
{
printf("顶点v%d或顶点v%d不存在,创建弧失败!!\n",i,j);
return ERROR;
}
p=G->AdjList[i].FirstArc;
while(p)
{
if(p->AdjVertex==j)
{
printf("已存在弧<v%d,v%d>,插入弧失败!\n",i,j);//插入弧重复,插入失败
return ERROR;
}
p=p->Next;
}
Insert=(ArcNode *)malloc(sizeof (ArcNode));
Insert->AdjVertex=j;
Insert->Next=G->AdjList[i].FirstArc; //头插法插入
G->AdjList[i].FirstArc=Insert; //头插法插入
G->AmountofArc++;//弧数量加一
printf("\n\n");
return CORRECT;
}
删除弧↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
int DeleteArc(Graph *G)
{
int i,j,k;
ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱
printf("删除弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
scanf("%d %d",&i,&j);
getchar();
for(p=G->AdjList[i].FirstArc;;p=p->Next)
{
pre=p;
if(p==NULL)//没有弧
{
printf("不存在弧<v%d,v%d>,删除弧失败!\n",i,j);
return ERROR;
}
if(p->AdjVertex==j)
{
if(p==G->AdjList[i].FirstArc) //被删除弧结点为第一个结点
{
del=p;
p=p->Next;
G->AdjList[i].FirstArc=p;
free(del); //删除弧结点
pre=NULL;
G->AmountofArc--; //弧数量减一
return CORRECT;
}
else //被删除弧结点不是第一个结点
{
del=p;
p=p->Next;
pre->Next=p;
free(del); //删除弧结点
G->AmountofArc--; //弧数量减一
return CORRECT;
}
}
}
printf("\n\n");
return CORRECT;
}
打印邻接矩阵↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
void PrintAdjMatrix(Graph *G)//邻接矩阵
{
int i,j,k,k_;
ArcNode *p;
for(i=0;i<G->AmountofVertex;i++)
for(j=0;j<G->AmountofVertex;j++)
{
if(G->AdjMatrix[i][j]!=0)
G->AdjMatrix[i][j]=0;//邻接矩阵初始化为0
}
for(i=0,k=0;k<G->AmountofVertex;i++)
{
if(G->AdjList[i].Vertex=='0') continue ;
for(p=G->AdjList[i].FirstArc;p;p=p->Next)
G->AdjMatrix[i][p->AdjVertex]=1;//相邻顶点赋值为1
k++;
}
printf("邻接矩阵:\n");
for(i=0,k=0;k<G->AmountofVertex;i++)
{
if(G->AdjList[i].Vertex=='0') continue;
for(j=0,k_=0;k_<G->AmountofVertex;j++)
{
if(G->AdjList[j].Vertex=='0') continue;
printf("%3d",G->AdjMatrix[i][j]);//输出矩阵
k_++;
}
k++;
printf("\n");
}
printf("\n\n");
}
打印邻接表↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
void PrintAdjGraph(Graph *G)//邻接表
{
int i=0,k=0;
ArcNode *p;
printf("邻接表:\n");
while(k<G->AmountofVertex)
{
if(G->AdjList[i].Vertex=='0')
k--;
else
{
for(p=G->AdjList[i].FirstArc;p;p=p->Next)
printf("<%c,%c>",G->AdjList[i].Vertex,G->AdjList[p->AdjVertex].Vertex);
printf("\n");
}
k++;
i++;
}
printf("\n\n");
}
查看顶点对应下标序号↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
int PrintVertexNum(Graph *G)//顶点下标序号表
{
int i,j,k;
ArcNode *p;
for(i=0,k=0;i<MAXIMUM;i++)
{
for(j=0;j<20;j++)
{
if(G->AdjList[j].Vertex=='0') continue;
printf("%c(%d)\t",G->AdjList[j].Vertex,j);//打印所有顶点和下标
k++;
if(k>=G->AmountofVertex)
{
printf("\n\n");
return CORRECT;
}
}
printf("\n");
}
printf("\n\n");
return CORRECT;
}
完整程序代码↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
#include <stdio.h>
#include <stdlib.h>
#define MAXIMUM 100
#define ERROR 1
#define CORRECT 0
typedef struct ArcNode
{
int AdjVertex;//邻接点下标
struct ArcNode *Next;
}ArcNode;
typedef struct VertexNode
{
char Vertex;//顶点信息
ArcNode *FirstArc;
}VertexNode[MAXIMUM];
typedef struct Graph//有向图
{
VertexNode AdjList;//邻接表
int AdjMatrix[MAXIMUM][MAXIMUM];//邻接矩阵
int AmountofVertex;//顶点数
int AmountofArc;//边数
}Graph;
int CreateGraph(Graph *G)//创建有向图
{
int i,j;
if(G==NULL)
{
printf("创建有向图失败!\n");//图创建失败
return ERROR;
}
else
printf("成功创建有向图\n");//图创建成功
G->AmountofArc=0;//0条边
G->AmountofVertex=0;//0个顶点
for(i=0;i<MAXIMUM;i++)
{
G->AdjList[i].FirstArc=NULL;//所有顶点集指向NULL
G->AdjList[i].Vertex='0';//所有顶点赋值为字符0
}
printf("\n");
return CORRECT;
}
int InsertVertex(Graph *G)//插入顶点
{
int k;
char vertex;
ArcNode *p;
printf("请输入要插入顶点的信息(一个字母)\n");//插入顶点
scanf("%c",&vertex);
getchar();
for(k=0;k<MAXIMUM;k++)
if(G->AdjList[k].Vertex=='0')
{
G->AdjList[k].Vertex=vertex;
G->AmountofVertex++;//顶点数加一
printf("\n");
return CORRECT;
}
printf("顶点数组集已满!插入失败!\n");//数组元素满
printf("\n");
return ERROR;
}
int DeleteVertex(Graph *G)//删除顶点(同时删除所有该顶点相关的弧)
{
int i,j,k;
ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱
printf("删除顶点vi,以及与v相关的所有弧,请依次输入顶点vi下标\n");
scanf("%d",&i);
getchar();
G->AdjList[i].Vertex='0';//删除顶点信息
G->AmountofVertex--;//顶点数减一
p=G->AdjList[i].FirstArc;
G->AdjList[i].FirstArc=NULL;
while(p) //删除出度的弧
{
del=p;
p=p->Next;
free(del);
G->AmountofArc--;//弧数量减一
}
for(k=0;k<=G->AmountofVertex;k++)//删除入度的弧
{
p=G->AdjList[k].FirstArc;
while(p)
{
if(p->AdjVertex==i)
{
if(p==G->AdjList[k].FirstArc)//被删除弧结点为第一个结点
{
del=p;
p=p->Next;
G->AdjList[k].FirstArc=p;
pre=NULL;
free(del);
G->AmountofArc--;//弧数量减一
break;
}
else
{
del=p;
p=p->Next;
pre->Next=p;
free(del);
G->AmountofArc--;//弧数量减一
break;
}
}
pre=p;
p=p->Next;
}
}
printf("\n\n");
return CORRECT;
}
int InsertArc(Graph *G)
{
int i,j;
ArcNode *p,*Insert;
printf("插入弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
scanf("%d %d",&i,&j);
getchar();
if(G->AdjList[i].Vertex=='0'||G->AdjList[j].Vertex=='0')//不存在顶点vi或vj,插入失败
{
printf("顶点v%d或顶点v%d不存在,创建弧失败!!\n",i,j);
return ERROR;
}
p=G->AdjList[i].FirstArc;
while(p)
{
if(p->AdjVertex==j)
{
printf("已存在弧<v%d,v%d>,插入弧失败!\n",i,j);//插入弧重复,插入失败
return ERROR;
}
p=p->Next;
}
Insert=(ArcNode *)malloc(sizeof (ArcNode));
Insert->AdjVertex=j;
Insert->Next=G->AdjList[i].FirstArc; //头插法插入
G->AdjList[i].FirstArc=Insert; //头插法插入
G->AmountofArc++;//弧数量加一
printf("\n\n");
return CORRECT;
}
int DeleteArc(Graph *G)
{
int i,j,k;
ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱
printf("删除弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
scanf("%d %d",&i,&j);
getchar();
for(p=G->AdjList[i].FirstArc;;p=p->Next)
{
pre=p;
if(p==NULL)//没有弧
{
printf("不存在弧<v%d,v%d>,删除弧失败!\n",i,j);
return ERROR;
}
if(p->AdjVertex==j)
{
if(p==G->AdjList[i].FirstArc) //被删除弧结点为第一个结点
{
del=p;
p=p->Next;
G->AdjList[i].FirstArc=p;
free(del); //删除弧结点
pre=NULL;
G->AmountofArc--; //弧数量减一
return CORRECT;
}
else //被删除弧结点不是第一个结点
{
del=p;
p=p->Next;
pre->Next=p;
free(del); //删除弧结点
G->AmountofArc--; //弧数量减一
return CORRECT;
}
}
}
printf("\n\n");
return CORRECT;
}
void PrintAdjMatrix(Graph *G)//邻接矩阵
{
int i,j,k,k_;
ArcNode *p;
for(i=0;i<G->AmountofVertex;i++)
for(j=0;j<G->AmountofVertex;j++)
{
if(G->AdjMatrix[i][j]!=0)
G->AdjMatrix[i][j]=0;//邻接矩阵初始化为0
}
for(i=0,k=0;k<G->AmountofVertex;i++)
{
if(G->AdjList[i].Vertex=='0') continue ;
for(p=G->AdjList[i].FirstArc;p;p=p->Next)
G->AdjMatrix[i][p->AdjVertex]=1;//相邻顶点赋值为1
k++;
}
printf("邻接矩阵:\n");
for(i=0,k=0;k<G->AmountofVertex;i++)
{
if(G->AdjList[i].Vertex=='0') continue;
for(j=0,k_=0;k_<G->AmountofVertex;j++)
{
if(G->AdjList[j].Vertex=='0') continue;
printf("%3d",G->AdjMatrix[i][j]);//输出矩阵
k_++;
}
k++;
printf("\n");
}
printf("\n\n");
}
void PrintAdjGraph(Graph *G)//邻接表
{
int i=0,k=0;
ArcNode *p;
printf("邻接表:\n");
while(k<G->AmountofVertex)
{
if(G->AdjList[i].Vertex=='0')
k--;
else
{
for(p=G->AdjList[i].FirstArc;p;p=p->Next)
printf("<%c,%c>",G->AdjList[i].Vertex,G->AdjList[p->AdjVertex].Vertex);
printf("\n");
}
k++;
i++;
}
printf("\n\n");
}
int PrintVertexNum(Graph *G)//顶点下标序号表
{
int i,j,k;
ArcNode *p;
for(i=0,k=0;i<MAXIMUM;i++)
{
for(j=0;j<20;j++)
{
if(G->AdjList[j].Vertex=='0') continue;
printf("%c(%d)\t",G->AdjList[j].Vertex,j);//打印所有顶点和下标
k++;
if(k>=G->AmountofVertex)
{
printf("\n\n");
return CORRECT;
}
}
printf("\n");
}
printf("\n\n");
return CORRECT;
}
int main(void)
{
int a;
Graph *G;
G=(Graph *)malloc(sizeof (Graph));
CreateGraph(G);
while(1)
{
printf("当前总弧数为:%d\n",G->AmountofArc);
printf("当前顶点数为:%d\n",G->AmountofVertex);
printf("输入9查看操作序号\n\n");
scanf("%d",&a);
getchar();
switch(a)
{
case 1:InsertVertex(G); break;
case 2:DeleteVertex(G); break;
case 3:InsertArc(G); break;
case 4:DeleteArc(G); break;
case 5:PrintAdjGraph(G); break;
case 6:PrintAdjMatrix(G); break;
case 7:PrintVertexNum(G); break;
case 9:
printf("****************************序号菜单*************************\n");
printf("请输入操作序号:\n");
printf("(1)插入顶点\t\t(2)删除顶点及所有相关弧\t\t(3)插入弧\n\n");
printf("(4)删除弧\t\t(5)打印邻接表\t\t(6)打印邻接矩阵\n\n");
printf("(7)当前已插入顶点的下标:\t\t(0)结束程序\n\n");
printf("***************************************************************\n\n");break;
case 0:return CORRECT;
}
}
return CORRECT;
}
示例↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
运行结果↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓