#include <stdio.h>
#include <corecrt_malloc.h>
#define MAX 10
//数据
char V[] = { 'a','b','c','d' };
char edges[][2] = { {'a','b'},{'a','d'},{'b','c'},{'b','d'},{'c','d'} };


//定义结构体 三层 一层是邻接表  包含顶点数  边数  顺序表的长度
//二层是顺序表的节点  包含节点内寸的数据 以及第一个指针指向链表的位置
//三层是链表节点  包含一个数据(数据用int 及数据在顺序表中的位置来表示  当顺序表中data较大可以减少内存的使用)一个NEXT指针
//结构体的创建时候要3,2,1要不编译过程出错

typedef struct P3 {
	int n;
	struct P3* next;
}P3, * PP3;

typedef struct P2 {
	char data;
	P3* first;
}P2, * PP2;


typedef struct P1 {
	int len_edge;//边的个数
	int len_v;//顶点个数
	P2 SXB[MAX];
}P1,*PP1;

//查找数据在顺序表中位置
int get(PP1 k, char a) {
	int i = 0;
	for (i; i < k->len_v; i++) {
		if (k->SXB[i].data == a) {
			return i;
		}
	}
	return -1;
}

//链接链表节点  查找到最后一个链表节点让后在其后面链接新节点  传入的参数都是链表节点指针
void link(PP3 k, PP3 node) {
	//先查找链表最后一个节点
	PP3 m;
	m = k;
	while (m->next != NULL) {
		m = m->next;
	}
	m->next = node;
}

//遍历输出邻接表
void pout(PP1 pg) {
	//创建一个临时链表指针
	PP3 m;
	//按照顺序表来遍历  遍历一个点看看是否有链表 有链表就遍历链表没有就下一个顺序表的节点
	for (int i = 0; i < pg->len_v; i++) {
		printf("%c", pg->SXB[i].data);
		printf("\t");
		m = pg->SXB[i].first;
		while (m != NULL) {		
			printf("%c", pg->SXB[m->n].data);
			m = m->next;
		}
		printf("\n");
	}
	return;
}
//无向图的构建
int main() {
	//创建一个邻接表
	PP1 pg;
	pg = (PP1)calloc(1, sizeof(P1));//申请邻接表的空间 内存全部设为0
	//初始化邻接表的边值和顶点数
	pg->len_edge = sizeof(edges)/sizeof(edges[0]);  //用sizeof 来计算数组中元素的数量 
	pg->len_v = sizeof(V)/sizeof(V[0]);
	//邻接表的顺序表中填充顶点
	for (int i = 0;i< pg->len_v; i++) {
		pg->SXB[i].data = V[i];//按照数组V中的顺序依次放入顺序表中
		pg->SXB[i].first = NULL; //这里初始时候已经是NULL 
	}
	//邻接表边的填充  先根据边的两个顶点 找到链表节点应该在那个位置 让后插入即可
	int j1, k2;//用来接收顶点在顺序表中的位置(下标)
	PP3 node1, node2;//用来做临时链表节点  
	for (int i = 0; i < pg->len_edge; i++) {
		//获得边两头数据的位置
		j1 = get(pg,edges[i][0]);
		k2 = get(pg,edges[i][1]);
		//为链表节点申请空间
		node1 = (PP3)calloc(1, sizeof(P3));
		node2 = (PP3)calloc(1, sizeof(P3));
		//初始化链表节点  其NEXT在申请时就设为NULL了  不再设置了	
		node1->n = j1;
		node2->n = k2;
		//先给第一个节点后面的链表插入节点  如果链表还没节点直接让FIRST指向节点即可  如果有节点就遍历到最后一个节点在链接
		if (pg->SXB[j1].first == NULL) {
			pg->SXB[j1].first = node2;
		}
		else {
			link(pg->SXB[j1].first, node2);
		}
		//同理给尾节点链表插入节点 应为是无向图 所以 有A->B 就有 B->A
		if (pg->SXB[k2].first == NULL) {
			pg->SXB[k2].first = node1;
		}
		else {
			link(pg->SXB[k2].first, node1);
		}
	}
	pout(pg);
	return 0;
}