# 邻接表创建图

//邻接表创建无向网图
{
int vexNum, edgeNum;
printf("请输入顶点和边数(用逗号隔开):");
scanf("%d,%d",&vexNum,&edgeNum);
graph->edgeNun = edgeNum;
graph->vexNum = vexNum;
getchar();//消除上面的换行符
printf("请输入顶点的值:");
////输入顶点值
//for (int i = 0; i < vexNum; i++)
//{
//	scanf("%c", &graph->list[i].data);
//	graph->list[i].first = NULL;//初始化first指针域
//}
////输入边表数据
//for (int k = 0; k < edgeNum; k++)
//{
//	int i, j, w;
//	printf("请输入(Vi,Vj)对应的顶点下标和权值(用逗号隔开):");
//	scanf("%d,%d,%d", &i, &j, &w);
//	//i -> j i出度到j
//	EdgeNode* edge = (EdgeNode*)malloc(sizeof(EdgeNode));//创建边结点
//	edge->vexIndex = j;
//	edge->weight = w;
//	edge->next = graph->list[i].first;//头插法 往单链表插入结点
//	graph->list[i].first = edge;
//	//由于是无向的，实现上是双向的，故边数据(Vj,Vi)也要创建
//	//j -> i j出度到i
//	edge = (EdgeNode*)malloc(sizeof(EdgeNode));
//	edge->vexIndex = i;
//	edge->weight = w;
//	edge->next = graph->list[j].first;;
//	graph->list[j].first = edge;

//}

//每个单链表的尾指针数组
EdgeNode** tailArr = (EdgeNode**)malloc(sizeof(EdgeNode*)*vexNum);
//输入顶点值
for (int i = 0; i < vexNum; i++)
{
scanf("%c", &graph->list[i].data);
graph->list[i].first = (EdgeNode*)malloc(sizeof(EdgeNode));//创建头结点，采用尾插入
graph->list[i].first->next = NULL;
tailArr[i] = graph->list[i].first;
}
//输入边表数据
for (int k = 0; k < edgeNum; k++)
{
int i, j, w;
printf("请输入(Vi,Vj)对应的顶点下标和权值(用逗号隔开):");
scanf("%d,%d,%d", &i, &j, &w);
//i -> j i出度到j
EdgeNode* edge = (EdgeNode*)malloc(sizeof(EdgeNode));//创建边结点
edge->vexIndex = j;
edge->weight = w;
edge->next = NULL;
tailArr[i]->next = edge;	//采用尾插法
tailArr[i] = edge;

edge = (EdgeNode*)malloc(sizeof(EdgeNode));
edge->vexIndex = i;
edge->weight = w;
edge->next = NULL;
tailArr[j]->next = edge;
tailArr[j] = edge;
}
//将头结点释放
for (int i = 0; i < vexNum; i++)
{
}
return graph;
}

# 邻接表的深度优先遍历

void DFTGraphAdjList(GraphAdjList* graph,int vexIndex)
{
//访问过不再访问
if (g_visited[vexIndex] == TRUE)
{
return;
}
g_visited[vexIndex] = TRUE;

EdgeNode* node = graph->list[vexIndex].first;
while (node)
{
node = node->next;
}
return;
}

//深度优先遍历邻接表
{
if (NULL == graph)
{
return;
}
for (int i = 0; i < graph->vexNum; i++)
{
g_visited[i] = FALSE;
}
for (int i = 0; i < graph->vexNum; i++)
{
if (g_visited[i] == FALSE)
{
}
}

return;
}

# 邻接表的广度优先遍历

//广度优先遍历邻接表
{

if (NULL == graph)
{
return;
}
Queue queue;
InitQueue(&queue);
//初始化顶点都没有访问过
for (int i = 0; i < graph->vexNum; i++)
{
g_visited[i] = FALSE;
}
for (int i = 0; i < graph->vexNum; i++)
{
if (g_visited[i] == FALSE)
{
g_visited[i] = TRUE;
VertexType vex = graph->list[i].data;
EnQueue(&queue, i);//将访问过的顶点下标入队
//为什么这里要循环出队呢？出队获取已经访问过结点的下标，在内层的for继续访问其相关联结点，将减少外层for循环进入if次数
while (!EmptyQueue(&queue))
{
int vexIndex;
DeQueue(&queue, &vexIndex);//将访问过的顶点下标出队
EdgeNode* node = graph->list[vexIndex].first;
//将该节点的连接的结点且没有被访问过的结点进行访问，然后入队
while (node != NULL && g_visited[node->vexIndex] == FALSE)
{
g_visited[node->vexIndex] = TRUE;
VertexType vex = graph->list[node->vexIndex].data;
EnQueue(&queue, node->vexIndex);
node = node->next;
}
}

}
}
return;
}

# 代码汇总

## Queue.h

#pragma once
#ifndef __QUEUE_H__
#define __QUEUE_H__

typedef int EleType;//元素类型
typedef enum { ERROR, OK } Status;
typedef enum {FALSE,TRUE} Boolean;

//队列结点
typedef struct QueueNode
{
EleType data;
struct QueueNode* next;
}QueueNode;

//队列
typedef struct Queue
{
QueueNode* front;
QueueNode* tail;
}Queue;

//队列初始化
void InitQueue(Queue* queue);

//入队
int EnQueue(Queue* queue, EleType data);

//出队
int DeQueue(Queue* queue, EleType* data);

//队列是否为空
int EmptyQueue(Queue* queue);

#endif // !__QUEUE_H__


## Queue.c

#include <stdlib.h>
#include "Queue.h"

//队列初始化
void InitQueue(Queue* queue)
{
queue->front = NULL;
queue->tail = NULL;
return;
}

//入队
int EnQueue(Queue* queue, EleType data)
{
if (NULL == queue)
{
return ERROR;
}
QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
node->data = data;
node->next = NULL;
if (queue->front == NULL)
{
queue->front = queue->tail = node;
}
else
{
queue->tail->next = node;
queue->tail = node;
}
return OK;
}
//出队
int DeQueue(Queue* queue, EleType* data)
{
if (NULL == queue)
{
return ERROR;
}
if (!EmptyQueue(queue))
{
QueueNode* node = queue->front;
*data = node->data;
queue->front = queue->front->next;
if (NULL != node)
{
free(node);
node = NULL;
}
//队列的最后一个元素出队列后，tail指针也要置为空
if (EmptyQueue(queue))
{
queue->tail = queue->front;
}
}
return OK;
}

//队列是否为空
int EmptyQueue(Queue* queue)
{
if (NULL == queue)
{
return ERROR;
}
if (queue->front == NULL)
{
return TRUE;
}
return FALSE;
}

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include "Queue.h"
#define MAX_VERTEX 100
typedef char VertexType;//顶点类型
typedef int EdgeType;//边上权值类型
//边表结点数据结构
typedef struct EdgeNode
{
int vexIndex;//顶点下标
EdgeType weight;//权值
struct EdgeNode* next;	//指向下一个结点
}EdgeNode;
Boolean g_visited[MAX_VERTEX] = { 0 };//全局变量 顶点访问标志位数组
//顶点表数据结构
typedef struct VextexNode
{
VertexType data;
EdgeNode* first;//边表第一个结点

{
int vexNum, edgeNun;//顶点，边 的数量

//邻接表创建无向网图
{
int vexNum, edgeNum;
printf("请输入顶点和边数(用逗号隔开):");
scanf("%d,%d",&vexNum,&edgeNum);
graph->edgeNun = edgeNum;
graph->vexNum = vexNum;
getchar();//消除上面的换行符
printf("请输入顶点的值:");
////输入顶点值
//for (int i = 0; i < vexNum; i++)
//{
//	scanf("%c", &graph->list[i].data);
//	graph->list[i].first = NULL;//初始化first指针域
//}
////输入边表数据
//for (int k = 0; k < edgeNum; k++)
//{
//	int i, j, w;
//	printf("请输入(Vi,Vj)对应的顶点下标和权值(用逗号隔开):");
//	scanf("%d,%d,%d", &i, &j, &w);
//	//i -> j i出度到j
//	EdgeNode* edge = (EdgeNode*)malloc(sizeof(EdgeNode));//创建边结点
//	edge->vexIndex = j;
//	edge->weight = w;
//	edge->next = graph->list[i].first;//头插法 往单链表插入结点
//	graph->list[i].first = edge;
//	//由于是无向的，实现上是双向的，故边数据(Vj,Vi)也要创建
//	//j -> i j出度到i
//	edge = (EdgeNode*)malloc(sizeof(EdgeNode));
//	edge->vexIndex = i;
//	edge->weight = w;
//	edge->next = graph->list[j].first;;
//	graph->list[j].first = edge;

//}

//每个单链表的尾指针数组
EdgeNode** tailArr = (EdgeNode**)malloc(sizeof(EdgeNode*)*vexNum);
//输入顶点值
for (int i = 0; i < vexNum; i++)
{
scanf("%c", &graph->list[i].data);
graph->list[i].first = (EdgeNode*)malloc(sizeof(EdgeNode));//创建头结点，采用尾插入
graph->list[i].first->next = NULL;
tailArr[i] = graph->list[i].first;
}
//输入边表数据
for (int k = 0; k < edgeNum; k++)
{
int i, j, w;
printf("请输入(Vi,Vj)对应的顶点下标和权值(用逗号隔开):");
scanf("%d,%d,%d", &i, &j, &w);
//i -> j i出度到j
EdgeNode* edge = (EdgeNode*)malloc(sizeof(EdgeNode));//创建边结点
edge->vexIndex = j;
edge->weight = w;
edge->next = NULL;
tailArr[i]->next = edge;	//采用尾插法
tailArr[i] = edge;

edge = (EdgeNode*)malloc(sizeof(EdgeNode));
edge->vexIndex = i;
edge->weight = w;
edge->next = NULL;
tailArr[j]->next = edge;
tailArr[j] = edge;
}
//将头结点释放
for (int i = 0; i < vexNum; i++)
{
}
return graph;
}
//打印 邻接表的无向图
{
printf("顶点数据:\n");
//顶点数据
for (int i = 0; i < graph->vexNum; i++)
{
printf("%c ",graph->list[i].data);
}
printf("\n边数据:\n");
EdgeNode* temp = NULL;
//边数据
for (int i = 0; i < graph->vexNum; i++)
{
temp = graph->list[i].first;
while (temp)
{
printf("%d\t",temp->weight);
temp = temp->next;
}
printf("\n");
}
return;
}
//访问顶点元素
{
printf("%c ", data);
return;
}
{
//访问过不再访问
if (g_visited[vexIndex] == TRUE)
{
return;
}
g_visited[vexIndex] = TRUE;

EdgeNode* node = graph->list[vexIndex].first;
while (node)
{
node = node->next;
}
return;
}

//深度优先遍历邻接表
{
if (NULL == graph)
{
return;
}
for (int i = 0; i < graph->vexNum; i++)
{
g_visited[i] = FALSE;
}
for (int i = 0; i < graph->vexNum; i++)
{
if (g_visited[i] == FALSE)
{
}
}

return;
}
//广度优先遍历邻接表
{

if (NULL == graph)
{
return;
}
Queue queue;
InitQueue(&queue);
//初始化顶点都没有访问过
for (int i = 0; i < graph->vexNum; i++)
{
g_visited[i] = FALSE;
}
for (int i = 0; i < graph->vexNum; i++)
{
if (g_visited[i] == FALSE)
{
g_visited[i] = TRUE;
VertexType vex = graph->list[i].data;
EnQueue(&queue, i);//将访问过的顶点下标入队
//为什么这里要循环出队呢？出队获取已经访问过结点的下标，在内层的for继续访问其相关联结点，将减少外层for循环进入if次数
while (!EmptyQueue(&queue))
{
int vexIndex;
DeQueue(&queue, &vexIndex);//将访问过的顶点下标出队
EdgeNode* node = graph->list[vexIndex].first;
//将该节点的连接的结点且没有被访问过的结点进行访问，然后入队
while (node != NULL && g_visited[node->vexIndex] == FALSE)
{
g_visited[node->vexIndex] = TRUE;
VertexType vex = graph->list[node->vexIndex].data;
EnQueue(&queue, node->vexIndex);
node = node->next;
}
}

}
}
return;
}

int main(int argc, char *argv[])
{
printf("深度优先遍历邻接表:\n");
printf("\n广度优先遍历邻接表:\n");
printf("\n");
return 0;
}