图的BFS和DFS
用到的文件路径:
结点:C:\Users\lu\Desktop\结点.txt
边:C:\Users\lu\Desktop\边.txt
vs2015以上不能直接用fopen函数,需要改变、配置;给加上一句
_CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#define M 100
typedef struct enode//边表结点
{
int adjvex;
struct enode *next;
}Edgenode;
typedef struct vnode//头结点
{
char vertex;
Edgenode * Firstedge;
}Vertenode;
typedef struct tu//存图各顶点以及顶点数和边数
{
Vertenode ad[M];
int n, e;
}MP;
int vis[M];//标记数组,用来记录结点是否被访问过,0表示没有被访问过,1表示被访问;
void fun()
{
int i = 0;
char bar[102] = { 0 };
printf("数据输入中,请稍后\n");
while (i <= 50)
{
printf("[%-50s][%3d%%]\r", bar, i * 2);
Sleep(60);
bar[i++] = '*';
bar[i] = '\0';
}
printf("\n数据输入完毕\n");
}
void create(MP *g, int c)//后插法建立边表结点
{
int i;
int a, b;
FILE *fp;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
printf("**********************程序说明***********************\n");
printf("* 结点文件路径:C:\\Users\\lu\\Desktop\\结点.txt *\n");
printf("* 边文件路径:C:\\Users\\lu\\Desktop\\边.txt *\n");
printf("*****************************************************\n\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
printf("****以下为后插法建立邻接表****\n");
Edgenode *s;//边表结点
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
printf("请输入图的结点数和边数:");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
scanf_s("%d%d", &g->n, &g->e);//结点数和边数
getchar();
fp = fopen("C:\\Users\\lu\\Desktop\\结点.txt", "r");
fun();
Sleep(300);
for (i = 0; i < g->n; i++)
{
fscanf_s(fp, "%c", &g->ad[i].vertex,1);
g->ad[i].Firstedge = NULL;
}
fclose(fp);
fp = fopen("C:\\Users\\lu\\Desktop\\边.txt", "r");
/*getchar();*/
for (i = 0; i < g->e; i++)//后插法建立边表结点
{
fscanf_s(fp, "%d%d", &a, &b);
s = (Edgenode*)malloc(sizeof(Edgenode));
s->adjvex = b;
s->next = g->ad[a].Firstedge;
g->ad[a].Firstedge = s;
if (c == 0)
{
s = (Edgenode*)malloc((sizeof(Edgenode)));
s->adjvex = a;
s->next = g->ad[b].Firstedge;
g->ad[b].Firstedge = s;
}
}
fclose(fp);
}
void print(MP *g)//输出邻接表
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
printf("该图的邻接表输出如下:\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
int i;
Edgenode *p1;//边表结点类型指针,用来输出邻接表;
for (i = 0; i < g->n; i++)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 5);
printf("%c***> ", g->ad[i].vertex);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
p1 = g->ad[i].Firstedge;
while (p1)
{
if (p1->next == NULL)
{
printf("%d", p1->adjvex);
p1 = p1->next;
}
else
{
printf("%d-->", p1->adjvex);
p1 = p1->next;
}
}
printf("\n");
}
}
void DFS(MP *g, int i)//遍历图中的连通分量---递归实现;
{
Edgenode *p1;//临时边表结点指针;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
printf("%c-->", g->ad[i].vertex);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
vis[i] = 1;
p1 = g->ad[i].Firstedge;
while (p1)
{
if (vis[p1->adjvex] == 0)
{
DFS(g, p1->adjvex);
}
p1 = p1->next;
}
}
void DFS_1(MP *g, int i)//遍历图中每个连通分量---非递归实现
{
Edgenode *p1;
Edgenode *st[M];
int top = -1;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
printf("%c***>", g->ad[i].vertex);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
vis[i] = 1;
p1 = g->ad[i].Firstedge;
while (top>-1 || p1)
{
if (p1)
{
if (vis[p1->adjvex])
{
p1 = p1->next;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
printf("%c***>", g->ad[p1->adjvex].vertex);
vis[p1->adjvex] = 1;
st[++top] = p1;
p1 = g->ad[p1->adjvex].Firstedge;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
}
else
{
if (top >-1)
{
p1 = st[top--];
p1 = p1->next;
}
}
}
}
void DFStu(MP *g,int c)//遍历每一个连通分量,即:遍历整个图;
{
int i;
for (i = 0; i < g->n; i++)
{
vis[i] = 0;
}
if (c == 0)
{
printf("递归DFS输出:");
for (i = 0; i < g->n; i++)
{
if (vis[i] == 0)//图有几个连通分量,就执行几次递归;
{
DFS(g, i);
}
}
printf("\n");
}
else if(c==1)
{
printf("非递归DFS输出:");
for (i = 0; i < g->n; i++)
{
if (vis[i] == 0)//图有几个连通分量,就执行几次递归;
{
DFS_1(g, i);
}
}
printf("\n");
}
}
void BFS(MP *g, int i)
{
int a;
Edgenode *p1;
int queue[M];//队列
int front, rear;//队首和队尾下标
front = rear = 0;//初始化
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
printf("%c--->", g->ad[i].vertex);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
vis[i] = 1;
queue[rear++] = i;//将i入队列
while (rear > front)
{
a = queue[front++];//取队首元素,并出队列;
p1 = g->ad[a].Firstedge;
while (p1)
{
if (vis[p1->adjvex] == 0)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
printf("%c--->", g->ad[p1->adjvex].vertex);
queue[rear++] = p1->adjvex;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
vis[p1->adjvex] = 1;
}
p1 = p1->next;
}
}
}
void BFStu(MP *g)
{
int i;
int count = 0;
for (i = 0; i < g->n; i++)
{
vis[i] = 0;
}
for (i = 0; i < g->n; i++)
{
if (vis[i] == 0)
{
BFS(g, i);
count++;
}
}
printf("\n该图的连通分量为:%d\n", count);
}
int main()
{
MP A;
MP *p;
p = &A;
int i, j;
create(p, 0);
print(p);
int c;
printf("BFS输出结果如下:\n");
BFStu(p);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
printf("请输入DFS类型(0表示递归or1表示非递归):");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
scanf_s("%d", &c);
DFStu(p,c);
return 0;
}