无向图邻接表实现
邻接表是一个顺序存储和链式存储相结合的结构体
顺序表里存储顶点的信息和指向下一个顶点的指针域
总体上类似于孩子兄弟表示法
因此结构体需求:
边表结构:
1, 该边指向哪个顶点?
2, 存储连接的下一个顶点的指针
顶点结构:
1,存储顶点的信息域
2,存储边表的指针域(指向第一个顶点)
图的结构:
1,存储顶点的数据域
2,当前图的边数和顶点数
#include <stdio.h>
#include <stdlib.h>
#define End '#' //输入该值表示该顶点为空
#define MaxVer 10 //最大顶点数
typedef char VerElemType; //顶点集数据
typedef struct EdgNode{//边表
int isVer; //该边指向的具体顶点
struct EdgNode *next;//指向下一个结点的指针
int info; //边的权值,若不需要权,直接把这行去掉即可
}EdgNode;
typedef struct VerNode{//顶点表
VerElemType verData;//存储顶点的数据域
EdgNode *first; //存储该顶点指向的第一个顶点
}VerNode,AdjList[MaxVer];//AdjList表示邻接表类型
typedef struct{//邻接表的结构体定义
AdjList verList;//邻接表的顶点表
int verNum,edgNum;//当前图的边和顶点的个数
}ALGraph;
//创建邻接表
//1.初始化表中信息
void InitALGraph(ALGraph &G){
G.verList[0].verData = End;//将首顶点设置为判空顶点,也为保证图的顶点不为空的定义
G.edgNum = 0;
G.verNum = 1;
G.verList[0].first = NULL;//将首顶点指向的第一个顶点为空
}
//2.创建图的顶点集
void CreateALGraphVer(ALGraph &G){
printf("\n请输入图的顶点,输入#结束\n");
VerElemType inVer; //输入的顶点值
scanf("%c",&inVer);
int i = 0;//表示当前输入了多少合法的顶点
while(inVer != End && G.verNum < MaxVer){
G.verList[i++].verData = inVer;
getchar();//吸收换行符
G.verNum = i;
scanf("%c",&inVer);
}
}
//3.初始化边表,将每个顶点的第一条出边都设置为空
void InitALGraphEdg(ALGraph &G){
for(int i=0;i<G.verNum;i++){
G.verList[i].first = NULL;
}
}
//4.查找顶点下标的方法,为创建边表做准备
int LocateVer(ALGraph G,VerElemType e){
for(int i=0;i<G.verNum;i++){
if(G.verList[i].verData == e) return i;//找到则返回下标
}
return -1;//找不到则返回-1
}
//5.创建边表,在顶点间建立关系
void CreateALGraphEdg(ALGraph &G){
printf("\n 开始创建边表 \n");
printf("\n请输入您要创建的边条数\n");
scanf("%d",&G.edgNum);
VerElemType str,end; //某条边开始的顶点和结束的顶点
int i = 0;//记录当前创建了几条边
while(i < G.edgNum){//开始循环创建顶点间的关系
printf("\n请输入开始的顶点:");
getchar();
scanf("%c",&str);
printf("\n请输入结束的顶点:");
getchar();
scanf("%c",&end);
int s = LocateVer(G,str);
int e = LocateVer(G,end);
if(s == -1||e == -1){//判断输入的顶点是否有误
printf("\n输入的顶点有误,请重新输入!");
}else{//输入的顶点正确,开始建立边
EdgNode *p = (EdgNode *)malloc(sizeof(EdgNode));//生成边结点,使其插入到出发点边表里
p->isVer = e;//将新生成的结点的序号设置为e(也就是代表了结束顶点)
//将该边结点连接到出发顶点的后面
p->next = G.verList[s].first;
G.verList[s].first = p;
//如果是无向图,则再继续做对称结点来新增结点到结束顶点的边表中,如果是有向图不需要下面的步骤
EdgNode *q = (EdgNode *)malloc(sizeof(EdgNode));
q->isVer = s;
q->next = G.verList[e].first;
G.verList[e].first = q;
printf("\n已建立 %c->%c\n",str,end);
i++;//创建一条边成功!
}
}
printf("\n创建边表成功!\n");
}
//6.开始创建邻接表
bool CreateALGraph(ALGraph &G){
InitALGraph(G);//先初始化图
CreateALGraphVer(G);//开始创建图中顶点
if(G.verList[0].verData == End) return false;//如果该图为初始图,则直接结束
InitALGraphEdg(G);//初始化边表
CreateALGraphEdg(G);//创建边表
}
//展示邻接表
void ShowALGraph(ALGraph G){
printf("\n当前顶点有:");
for(int i=0;i<G.verNum;i++){
printf("%c ",G.verList[i].verData);
}
printf("\n———————邻接表为————————\n");
printf("顶点\t边表\n");
for(int i=0;i<G.verNum;i++){
printf("%c\t",G.verList[i].verData);
EdgNode *p = G.verList[i].first;//工作指针
while(p != NULL){//当工作指针的下一指针不为空时,输出工作指针所指结点
printf("%c",G.verList[p->isVer].verData);
p = p->next;
if(p!=NULL) printf("->");//还有下个顶点,那就给它加个箭头
}
printf("\n");
}
}
int main(){
ALGraph G;
CreateALGraph(G);
ShowALGraph(G);
}