邻接表:图的常用储存结构之一,由表头结点和表结点两部分组成,其中表头结点存储图的各顶点,表结点用单向链表存储表头结点所对应顶点的相邻顶点(也就是表示了图的边)。在有向图里表示表头结点指向其它结点(a->b),无向图则表示与表头结点相邻的所有结点(a—b)
以一个无向图为例
结构定义:
//表头结点(表示图的顶点)
struct vnode{
char data; //顶点数据,这里用字符表示
struct arcnode * firstarc; //指针指向第一条边
};
//表结点(表示图的边)
struct arcnode{
int wt; //权重
int adjvex; //顶点下标
struct arcnode *nextarc; //指针指向下一条边
};
typedef struct arcnode * Arc;
//图
struct mgraph{
struct vnode vexs[100];
int vexsnum,arcnum; //顶点数,边数
} *g;
typedef struct mgraph* Graph;
建图并输出图
int findadj(char vexs,Graph g){
int i;
for(i=1;i<=g->vexsnum;i++){
if(vexs==g->vexs[i].data)
break;
}
return i;
}
//建图
Graph creategraph(){
Graph g1;
char vex;
g1=(Graph)malloc(sizeof(struct mgraph));
g1->arcnum=0;
g1->vexsnum=0;
printf("输入顶点,输入-代表结束\n");
scanf("%c",&vex); //输入顶点
while(vex!='-'){ //输入-后循环结束
g1->vexsnum++;
g1->vexs[g1->vexsnum].data=vex; //这里的结构数组vexs[]下标从1开始
g1->vexs[g1->vexsnum].firstarc=NULL;
printf("输入下一个顶点,输入-代表结束\n");
scanf(" %c",&vex); //%c前面加空格防止读取回车
}
int i;
int w; //边的权重
int adjvex; //顶点的下标
char avex; //边的另一个顶点
Arc p,b;
for(i=1;i<=g1->vexsnum;i++){
printf("输入%c的相邻顶点,输入-代表结束",g1->vexs[i].data);
scanf(" %c",&avex);
while(avex!='-'){ //输入-后循环结束
adjvex=findadj(avex,g1);
printf("输入边%c%c的权重\n",g1->vexs[i].data,avex);
scanf("%d",&w);
b=(Arc)malloc(sizeof(struct arcnode));
b->adjvex=adjvex;
b->wt=w;
b->nextarc=NULL;
//链表追加结点
p=g1->vexs[i].firstarc;
if(p!=NULL){
while(p->nextarc!=NULL)
p=p->nextarc;
p->nextarc=b;
}else
g1->vexs[i].firstarc=b;
g1->arcnum++;
printf("输入%c的相邻顶点,输入-代表结束",g1->vexs[i].data);
scanf(" %c",&avex);
}
}
return g1;
}
//图的输出
void printgraph(Graph g){
int i,k;
Arc p;
printf("———邻接表————\n");
for(i=1;i<=g->vexsnum;i++){
printf("%c ->",g->vexs[i].data);
p=g->vexs[i].firstarc;
while(p!=NULL){
printf("%4c",g->vexs[i].data);
k=p->adjvex;
printf("%2c",g->vexs[k].data);
printf("%2d",p->wt);
if(p->nextarc!=NULL)
printf(" ->");
p=p->nextarc;
}
printf("\n");
}
printf("\n");
printf("—————————\n");
printf("顶点总数为%4d\n",g->vexsnum);
printf("边的总数为%4d\n",g->arcnum);
}
void main(){
g=creategraph();
printgraph(g);
}
控制台输出