//本程序使用邻接矩阵和邻接表构造无向图,并进行DFS和BFS遍历全图;
//可移植性程序能在Linux/Mac os/Windows下运行;
//若有不足之处请提出,博主会尽所能修改;
//若是对您有用的话请点赞收藏或分享给它人;
//未经允许严禁抄袭以及转载;
//源代码奉上,希望能够对您有所启发;
//----------------------------------------------------------------------------------------------------;
//邻接矩阵.c
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXNUM 5
typedef int Item;
typedef struct
{
char mes[MAXNUM]; //结点信息;
int graph[MAXNUM][MAXNUM]; //邻接矩阵;
int size, edge; //图中顶点的个数及边的个数;
} AdjacentMatrix_Graph;
typedef struct qnode
{
Item value;
struct qnode *next;
} QNODE;
typedef struct
{
QNODE *front;
QNODE *rear;
} Queue;
void initialize_graph(AdjacentMatrix_Graph *g); //初始化一个邻接矩阵构造的图;
void dfs(AdjacentMatrix_Graph *g, int *visited, int source); //深度遍历连通图;
void dfs_traverse(AdjacentMatrix_Graph *g); //深度遍历非连通图;
void bfs_traverse(AdjacentMatrix_Graph *g); //广度遍历连通图或非连通图;
void print_graph(AdjacentMatrix_Graph *g); //打印整个图信息;
void initialize_queue(Queue *temp); //初始化空队列;
bool enqueue(Queue *temp, Item val); //添加元素至队列中;
bool queue_is_empty(Queue *temp); //判断队列是否为空;
bool dequeue(Queue *temp, Item *val); //从队列中删除元素;
int main(void)
{
AdjacentMatrix_Graph map;
initialize_graph(&map);
printf("深度优先搜索遍历图信息如下:\n");
dfs_traverse(&map);
printf("广度优先搜索遍历图信息如下:\n");
bfs_traverse(&map);
printf("此图的邻接矩阵信息如下:\n");
print_graph(&map);
return 0;
}
void initialize_graph(AdjacentMatrix_Graph *g)
{
char ch;
int i, j, k, vex1, vex2, weight;
g->edge = 0;
g->size = MAXNUM;
for (i = 0; i < g->size; i++)
{
for (j = 0; j < g->size; j++)
{
g->graph[i][j] = INT_MAX; //初始时所有顶点不邻接;
}
}
for (i = 0; i < g->size; i++)
{
g->mes[i] = 'a' + i; //5个结点信息分别是a,b,c,d,e;
}
for (i = 0; i < g->size; i++)
{
printf("请输入与%c结点相邻的结点和权值(#结束输入):\n", g->mes[i]);
for (j = 0; j < g->size; j++)
{
scanf("%c", &ch);
if (ch == '#')
{
getchar();
break;
}
scanf("%d", &weight);
for (k = 0; k < g->size; k++)
{
if (g->mes[k] == ch)
{
g->graph[i][k] = weight;
g->edge++;
}
}
getchar();
}
}
g->edge /= 2; //构造后边数除以2(无向图);
/*
输入示例(相邻结点及其权值):
b 5 c 3 #
a 5 d 7 e 4 #
a 3 d 6 #
b 7 c 6 e 1 #
b 4 d 7 #
*/
/*
此图二维数组如下:
a b c d e
a ∞ 5 3 ∞ ∞
b 5 ∞ ∞ 7 4
c 3 ∞ ∞ 6 ∞
d ∞ 7 6 ∞ 1
e ∞ 4 ∞ 1 ∞
*/
return;
}
void dfs(AdjacentMatrix_Graph *g, int *visited, int source)
{
int i;
visited[source] = 1;
printf("%c ", g->mes[source]); //打印结点信息;
for (i = 0; i < g->size; i++)
{
if (g->graph[source][i] != INT_MAX && !visited[i])
{
dfs(g, visited, i);
}
}
return;
}
void dfs_traverse(AdjacentMatrix_Graph *g)
{
int i;
int visited[g->size];
for (i = 0; i < g->size; i++)
{
visited[i] = 0;
}
for (i = 0; i < g->size; i++) //遍历非联通结点;
{
if (!visited[i])
{
dfs(g, visited, i);
}
}
putchar('\n');
return;
}
void bfs_traverse(AdjacentMatrix_Graph *g)
{
int i, j;
Queue temp;
int visited[g->size];
for (i = 0; i < g->size; i++)
{
visited[i] = 0;
}
initialize_queue(&temp);
for (i = 0; i < g->size; i++)
{
if (!visited[i])
{
visited[i] = 1;
printf("%c ", g->mes[i]);
enqueue(&temp, i); //图中首结点入队;
while (!queue_is_empty(&temp))
{
dequeue(&temp, &i); //图第i个结点出队;
for (j = 0; j < g->size; j++) //遍历关联结点;
{
if (!visited[j] && g->graph[i][j] != INT_MAX)
{
visited[j] = 1;
printf("%c ", g->mes[j]); //输出结点信息;
enqueue(&temp, j); //与i相关联的结点入队;
}
}
}
}
}
putchar('\n');
return;
}
void print_graph(AdjacentMatrix_Graph *g)
{
int i, j;
for (i = 0; i < g->size; i++)
{
for (j = 0; j < g->size; j++)
{
printf("%-15d", g->graph[i][j]);
}
putchar('\n');
}
return;
}
void initialize_queue(Queue *temp)
{
temp->front = temp->rear = NULL;
return;
}
bool enqueue(Queue *temp, Item val)
{
QNODE *newqnode = (QNODE *)malloc(sizeof(QNODE));
if (NULL == newqnode)
{
fprintf(stderr, "动态内存分配失败!本程序退出!\n");
exit(EXIT_FAILURE);
}
newqnode->value = val;
newqnode->next = NULL;
if (queue_is_empty(temp))
{
temp->front = newqnode; //添加新结点令队头指针指向此结点;
}
else
{
temp->rear->next = newqnode; //将新结点添加至队尾;
}
temp->rear = newqnode; //修改队尾指针指向新结点;
return true;
}
bool queue_is_empty(Queue *temp)
{
return NULL == temp->front;
}
bool dequeue(Queue *temp, Item *val)
{
if (queue_is_empty(temp))
{
return false;
}
QNODE *p = temp->front; //声明一个临时指针指向队头结点;
*val = p->value; //保存队头结点的数据;
temp->front = temp->front->next; //使得头指针指向队头结点的后继结点;
if (p == temp->rear) //最后一个元素出队时的情况;
{
temp->rear = NULL;
}
free(p);
return true;
}
//邻接表.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXNUM 5 //图中最多的结点个数;
typedef int Item;
typedef char node_type;
typedef struct arc_node
{
int pos;
int weight;
struct arc_node *next;
} Arcnode; //保存结点的相邻结点信息;
typedef struct node
{
node_type info;
Arcnode *next;
} Graphnode; //保存结点信息;
typedef struct graph
{
Graphnode vertexs[MAXNUM];
int arc, vertex;
} AdjacentList_Graph; //邻接表;
typedef struct qnode
{
Item value;
struct qnode *next;
} QNODE;
typedef struct
{
QNODE *front;
QNODE *rear;
} Queue;
Arcnode *make_node(const int pos, const int weight); //封装好的分配内存函数;
void initialize_graph(AdjacentList_Graph *g); //初始化一个邻接表构造的图;
void dfs(AdjacentList_Graph *g, int *visited, int source); //深度遍历连通图;
void dfs_traverse(AdjacentList_Graph *g); //深度遍历非连通图;
void bfs(AdjacentList_Graph *g, int *visited, int source); //广度遍历连通图;
void bfs_traverse(AdjacentList_Graph *g); //广度遍历非连通图;
void print_graph(AdjacentList_Graph *g); //打印整个图信息;
void initialize_queue(Queue *temp); //初始化空队列;
bool enqueue(Queue *temp, Item val); //添加元素至队列中;
bool queue_is_empty(Queue *temp); //判断队列是否为空;
bool dequeue(Queue *temp, Item *val); //从队列中删除元素;
Item get_front_value(Queue *temp);
int main(void)
{
AdjacentList_Graph map;
initialize_graph(&map);
printf("深度优先搜索遍历图信息如下:\n");
dfs_traverse(&map);
printf("广度优先搜索遍历图信息如下:\n");
bfs_traverse(&map);
printf("此图的邻接矩阵信息如下:\n");
print_graph(&map);
return 0;
}
Arcnode *make_node(const int pos, const int weight)
{
Arcnode *new_node = (Arcnode *)malloc(sizeof(Arcnode));
if (new_node == NULL)
{
exit(EXIT_FAILURE);
}
new_node->next = NULL;
new_node->weight = weight;
new_node->pos = pos;
return new_node;
}
void initialize_graph(AdjacentList_Graph *g)
{
char ch;
Arcnode *temp;
int i, j, k, num;
g->vertex = MAXNUM;
for (i = 0; i < g->vertex; i++)
{
g->vertexs[i].info = 'a' + i; //构造5个结点分别为a,b,c,d,e;
g->vertexs[i].next = NULL;
}
for (i = 0; i < g->vertex; i++)
{
printf("请输入与结点%c相邻的结点和权值(#结束输入)\n", g->vertexs[i].info);
for (j = 0; j < g->vertex; j++)
{
scanf("%c", &ch);
if (ch == '#')
{
getchar();
break;
}
scanf("%d", &num);
getchar();
for (k = 0; k < g->vertex; k++)
{
if (g->vertexs[k].info == ch) //寻找到ch结点后构造结点关系;
{
if (g->vertexs[k].next == NULL) //没有相邻结点时的情况;
{
g->vertexs[k].next = make_node(i, num);
}
else //已有相邻结点的情况;
{
temp = g->vertexs[k].next;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = make_node(i, num);
}
}
}
}
}
/*
输入示例(相邻结点及其权值):
b 5 c 3 #
a 5 d 7 e 4 #
a 3 d 6 #
b 7 c 6 e 1 #
b 4 d 1 #
*/
/*
此图相对次序如下:
a 1 2
b 0 3 4
c 0 3
d 1 2 4
e 1 3
*/
return;
}
void dfs(AdjacentList_Graph *g, int *visited, int source)
{
Arcnode *temp = NULL;
visited[source] = 1;
printf("%c ", g->vertexs[source].info); //输出当前结点的名称信息;
temp = g->vertexs[source].next; //寻找到temp指向的结点的相邻结点;
while (temp != NULL)
{
if (!visited[temp->pos])
{
dfs(g, visited, temp->pos);
}
temp = temp->next;
}
return;
}
void dfs_traverse(AdjacentList_Graph *g)
{
int i;
int visited[g->vertex];
for (i = 0; i < g->vertex; i++)
{
visited[i] = 0;
}
for (i = 0; i < g->vertex; i++) //遍历非联通结点;
{
if (!visited[i])
{
dfs(g, visited, i);
}
}
putchar('\n');
return;
}
void bfs(AdjacentList_Graph *g, int *visited, int source)
{
Item t;
int pos;
Queue line;
Arcnode *temp = NULL;
visited[source] = 1;
initialize_queue(&line); //初始化空队列;
enqueue(&line, source); //第source个结点入队;
while (!queue_is_empty(&line))
{
pos = get_front_value(&line); //获取队头结点;
printf("%c ", g->vertexs[pos].info); //输出队头结点的名称信息;
temp = g->vertexs[pos].next; //寻找到temp指向的结点的相邻结点;
while (temp != NULL)
{
if (!visited[temp->pos])
{
visited[temp->pos] = 1; //标记此结点已被访问过;
enqueue(&line, temp->pos); //相邻结点位置入队;
}
temp = temp->next;
}
dequeue(&line, &t);
}
putchar('\n');
return;
}
void bfs_traverse(AdjacentList_Graph *g)
{
int i;
int visited[g->vertex];
for (i = 0; i < g->vertex; i++)
{
visited[i] = 0;
}
for (i = 0; i < g->vertex; i++) //遍历非联通结点;
{
if (!visited[i])
{
bfs(g, visited, i);
}
}
return;
}
void print_graph(AdjacentList_Graph *g)
{
int i;
Arcnode *temp;
for (i = 0; i < g->vertex; i++)
{
printf("%c\t", g->vertexs[i].info);
temp = g->vertexs[i].next;
while (temp != NULL)
{
printf("相邻%c结点(权值:%d)\t", g->vertexs[temp->pos].info, temp->weight);
temp = temp->next;
}
putchar('\n');
}
putchar('\n');
return;
}
void initialize_queue(Queue *temp)
{
temp->front = temp->rear = NULL;
return;
}
bool enqueue(Queue *temp, Item val)
{
QNODE *newqnode = (QNODE *)malloc(sizeof(QNODE));
if (NULL == newqnode)
{
fprintf(stderr, "动态内存分配失败!本程序退出!\n");
exit(EXIT_FAILURE);
}
newqnode->value = val;
newqnode->next = NULL;
if (queue_is_empty(temp))
{
temp->front = newqnode; //添加新结点令队头指针指向此结点;
}
else
{
temp->rear->next = newqnode; //将新结点添加至队尾;
}
temp->rear = newqnode; //修改队尾指针指向新结点;
return true;
}
bool queue_is_empty(Queue *temp)
{
return NULL == temp->front;
}
bool dequeue(Queue *temp, Item *val)
{
if (queue_is_empty(temp))
{
return false;
}
QNODE *p = temp->front; //声明一个临时指针指向队头结点;
*val = p->value; //保存队头结点的数据;
temp->front = temp->front->next; //使得头指针指向队头结点的后继结点;
if (p == temp->rear) //最后一个元素出队时的情况;
{
temp->rear = NULL;
}
free(p);
return true;
}
Item get_front_value(Queue *temp)
{
if (!queue_is_empty(temp))
{
return temp->front->value;
}
return -1;
}
//----------------------------------------------------------------------------------------------------;
//-------------------------------------------------2020年11月9日-------------------------------------------------------;
扫描二维码关注公众号,回复:
12354448 查看本文章