在我的图的基本知识的博客中说到有两种存储方法,这个博客我来分享无向图的存储方式,邻接表法
名字中有邻接两个字,实际上就是跟邻接顶点有关的方法,也就是把邻接顶点,以链表的方式接在其相应顶顶点数组对应位置的后面。如下图:
大概就是这样。
那么我们要实现这种结构我们需要什么:
1.表示顶点的字符串。
2.表示存储顶点的数组。
3.实现存储邻接顶点的链表,实际意义也就是边的意思。
4.数组也要有个指针指向其所带的链表。
所以得出结论就是,一个带着指针的数据数组,好多个链表节点以其规则指针链接。
好,我们来实现基础工作,实现以上部分
typedef char VertexType[4];//表示顶点
//邻接链表
typedef struct Arcnode {//表示边
int verindex;//顶点的序号
struct Arcnode* next;//表示下一个
}NODE, *LPNODE;
typedef struct VNode {//顶点节点
VertexType data;//顶点数据
LPNODE firstnode;//代表邻接链表的头节点
}VNODE,*LPVNODE,ARRAY[10];
typedef struct graph {
int arcnum;
int vexnum;
ARRAY vextex; //结构体数组
}GR,*LPGR;
大致包括完毕
下面就是存储表的函数。
我们分析一下我们需要干什么:
我们需要知道几个顶点,几个边,然后就是插入,插入也就是无头链表头接法,但是这里要强调的是我们需要一个指针指向我们要插入的头节点位置,也就是我们需要数组顶点节点的二级指针。
还有就是,我们AB边是不是就是A,B互为邻接顶点,所以我们插入需要两边都要插入
插入的话,我们需要找到两顶点在数组的坐标才能插入,既然我们两个坐标都知道了,我们要是查询信息,我们可以用坐标查询,所以我们链表部分我们可以插入的数据插入为下标,不用再去费劲去查找字母了,复制字符串了
所以,我们需要查找下标函数,,链表头接法函数,创建链表节点函数,一口气实现吧
LPNODE createnode(int vexIndex) {
LPNODE newnode = (LPNODE)malloc(sizeof(NODE));
newnode->verindex = vexIndex;
newnode->next = NULL;
return newnode;
}
void insert(LPNODE* headnode, int vexindex) {
LPNODE newnode = createnode(vexindex);
newnode->next = *headnode;
*headnode = newnode;
}
int search(LPGR G, VertexType x) {
for (int i = 0; i < G->vexnum; i++) {
if (strcmp(x, G->vextex[i].data)==0) {
return i;
}
}
return -1;
}
LPGR creategraph() {
LPGR G = (LPGR)malloc(sizeof(GR));
printf("请输入要输入顶点和边的个数:");
scanf("%d%d", &G->vexnum, &G->arcnum);
printf("请输入%d个顶点\n", G->vexnum);
for (int i = 0; i < G->vexnum; i++) {
scanf("%s", G->vextex[i].data);
G->vextex[i].firstnode = NULL;
}
printf("请输入边的信息:\n");
VertexType v1, v2;
int posi;
int posj;
for (int i = 0; i < G->arcnum; i++) {//这里的查找跟上个矩阵法存储的插入查找坐标是一样的
scanf("%s%s", v1, v2);
posi = search(G, v1);
posj = search(G, v2);
//涉及到链表操作
insert(&G->vextex[posi].firstnode, posj);
insert(&G->vextex[posj].firstnode, posi);//相互反过来一插入就好
}
return G;
}
好了,我们的图邻接表法存储完毕了。
下面是检验并打印的时刻到了。就拿最上面的图来检验一下吧:
void print(LPGR G) {
for (int i = 0; i < G->vexnum; i++) {
printf("%s-->", G->vextex[i].data);
LPNODE pmove = G->vextex[i].firstnode;
while (pmove) {
printf("%s-->", G->vextex[pmove->verindex].data);
pmove = pmove->next;
}
printf("\n");
}
}
int main() {
LPGR G= creategraph();
print(G);
return 0;
}
打印结果如下:
发现存储的点是对的,顺序不对,这是因为,我们利用的是头节点插入法。
好了,到这,基础的数据结构已经完毕了,面试考到的数据结构以链表队列二叉树居多,图结构实际上在工作中并不是很常见。