深度优先遍历访问的边集合_无向图深度优先遍历(DFS)和广度优先遍历(BFS)算法...

本文详细介绍了无向图的深度优先遍历(DFS)和广度优先遍历(BFS)算法,包括它们的定义、实现步骤和代码示例。DFS利用递归或栈进行访问,BFS则使用队列进行。两种算法在遍历图时具有不同的特点,DFS深入探索,BFS则遍历所有相邻节点。同时还提供了C++代码实现这两种遍历方法。
摘要由CSDN通过智能技术生成

定义

深度优先遍历

(1)从图中某个初始顶点v出发,首先访问初始顶点v。

(2)选择一个与顶点v相邻且没被访问过的顶点w,再从w出发进行深度优先搜索,直到图中与当前顶点v邻接的所有顶点都被访问过为止。

(3) 利用递归实现,简单但是不好理解,时间复杂度 O(n+e)。

广度优先遍历

(1)访问初始点v,接着访问v的所有未被访问过的邻接点v1,v2,…,vt。

(2)按照v1,v2,…,vt的次序,访问每一个顶点的所有未被访问过的邻接点。

(3)依次类推,直到图中所有和初始点v有路径相通的顶点都被访问过为止。

(4) 利用队列实现, 时间复杂度 O(n+e).

实现代码

深度优先遍历算法

//深度优先遍历算法

void DFS(AdjGraph *G, int v)

{

ArcNode *p;

visited[v] = 1;

printf("%d ", v);

p = G->adjlist[v].firstarc;

while(p != NULL) //p == NULL is the break of circle

{

if(visited[p->adjvex] == 0)

DFS(G, p->adjvex);

p=p->nextarc;

}

}

广度优先遍历算法

//广度优先遍历算法

void BFS(AdjGraph *G, int v)

{

int w, i;

ArcNode *p;

SqQueue *qu;

InitQueue(qu);

int visited[MAXV];

for(i = 0; i < G->n; i++)

visited[i] = 0;

printf("%2d",v);

visited[v] = 1;

enQueue(qu, v);

while( !QueueEmpty(qu))

{

deQueue(qu, w);

p = G->adjlist[w].firstarc;

while(p!=NULL)

{

if(visited[p->adjvex] == 0)

{

printf("%2d", p->adjvex);

visited[p->adjvex] = 1;

enQueue(qu, p->adjvex);

}

p = p->nextarc;

}

}

printf("\n");

}

注意理解

注意,DFS是基于递归形式的, 主要是往深入的方向去遍历。 每次碰到可以读取输出的顶点就直接输出,并且将其视作是头节点数组,接着向它的下一个进行读取。

BFS则比较憨厚,他是直接在一个头节点数组走到黑,一直到读取NULL才肯回头。这时候,需要利用队列来保存被它错过的路口,给他提供后悔药。回头时队列出栈,出一颗后悔药给他吃,让它接着往下一个方向一直走。一直等到它把后悔药都吃完,然后就遍历结束了。

全部代码

#include

#include

#include

#include

#define ElemType int

#define maxsize 100

#define InfoType int

#define MAXV 100

#define MaxSize 100

#define INF 214748364

#define INFINITE INF

/

//邻接表的结构体定义

typedef struct ANode

{

int adjvex; //该边的邻接点的编号,即有向边指向的顶点编号

struct ANode *nextarc; //指向下一条边的指针

int weight; //边的相关的信息,如权值

} ArcNode; //边节点的类型

typedef struct Vnode

{

InfoType info; //顶点的其他信息

int count; //存放顶点入度

ArcNode *firstarc; //指向第一个边节点

} VNode; //邻接表的头节点的结构体类型

typedef struct

{

VNode adjlist[MAXV]; //头节点的数组

int n, e; //图的顶点数和边数

} AdjGraph; //整个邻接表的数据结构体类型

//

//邻接矩阵的结构体

typedef struct S

{

int no; //顶点的编号

InfoType info; //顶点的其他信息

} VertexType; //顶点的类型

typedef struct SS

{

int edges[MAXV][MAXV]; //邻接矩阵的数组

int n, e; //图的顶点数和边数

VertexType vexs[MAXV]; //存放顶点信息

} MatGraph;

///

typedef struct SSS

{

ElemType data[maxsize];

int front;

int rear;

} SqQueue; //队列的结构体

//Kruskal算法需要的简化图的结构体

typedef struct head

{

int u; //边的起始顶点

int v; //边的终止顶点

int w; //边的权值

} Edge;

///

///零零零零啦啦啦啦啦

int visited[MAXV] = {0};

///

//队列的操作函数集合

//由于队列的函数在另一个文件

//所以需要声明一下

void InitQueue(SqQueue *&q);

void DestoryQueue(SqQueue *&q);

bool QueueEmpty(SqQueue *q);

bool enQueue(SqQueue *&q, ElemType e);

bool deQueue(SqQueue *&q, ElemType &e);

/

//后序遍历需要的一些队列的基本函数

void InitQueue(SqQueue *&q)

{

q = (SqQueue *)malloc(sizeof(SqQueue));

q->front = q->rear = 0;

}

void DestoryQueue(SqQueue *&q)

{

free(q);

}

bool QueueEmpty(SqQueue *q)

{

return (q->front == q->rear);

}

bool enQueue(SqQueue *&q, ElemType e)

{

if ((q->rear + 1) % maxsize == q->front)

return false;

q->rear = (q->rear + 1) % maxsize;

q->data[q->rear] = e;

return true;

}

bool deQueue(SqQueue *&q, ElemType &e)

{

if (q->front == q->rear)

return false;

q->front = (q->front + 1) % maxsize;

e = q->data[q->front];

return true;

}

/

void CreateAdj(AdjGraph *&G, int A[MAXV][MAXV], int n, int e)

{

int i, j;

ArcNode *p;

G = (AdjGraph *)malloc(sizeof(AdjGraph));

for (i = 0; i < n; i++)

G->adjlist[i].firstarc = NULL;

for (i = 0; i < n; i++)

for (j = n - 1; j >= 0; j--)

if (A[i][j] != 0 && A[i][j] != INF)

{

p = (ArcNode *)malloc(sizeof(ArcNode));

p->adjvex = j;

p->weight = A[i][j];

p->nextarc = G->adjlist[i].firstarc;

G->adjlist[i].firstarc = p;

}

G->n = n;

G->e = e;

}

void DispAdj(AdjGraph *G) //输出邻接表G

{

int i;

ArcNode *p;

for (i = 0; i < G->n; i++)

{

p = G->adjlist[i].firstarc;

printf("%3d: ", i);

while (p != NULL)

{

if (p->weight != 2147483647) //2147483647

printf("%3d[%d]→", p->adjvex, p->weight);

p = p->nextarc;

}

printf("^\n");

}

}

void DestroyAdj(AdjGraph *&G) //销毁邻接表

{

int i;

ArcNode *pre, *p;

for (i = 0; i < G->n; i++) //扫描所有的单链表

{

pre = G->adjlist[i].firstarc; //p指向第i个单链表的首结点

if (pre != NULL)

{

p = pre->nextarc;

while (p != NULL) //释放第i个单链表的所有边结点

{

free(pre);

pre = p;

p = p->nextarc;

}

free(pre);

}

}

free(G); //释放头结点数组

}

//

//无向图邻接表的深度优先算法

void DFS(AdjGraph *G, int v)

{

ArcNode *p;

visited[v] = 1;

printf("%d ", v);

p = G->adjlist[v].firstarc;

while(p != NULL) //p == NULL is the break of circle

{

if(visited[p->adjvex] == 0)

DFS(G, p->adjvex);

p=p->nextarc;

}

}

//

void BFS(AdjGraph *G, int v)

{

int w, i;

ArcNode *p;

SqQueue *qu;

InitQueue(qu);

int visited[MAXV];

for(i = 0; i < G->n; i++)

visited[i] = 0;

printf("%2d",v);

visited[v] = 1;

enQueue(qu, v);

while( !QueueEmpty(qu))

{

deQueue(qu, w);

p = G->adjlist[w].firstarc;

while(p!=NULL)

{

if(visited[p->adjvex] == 0)

{

printf("%2d", p->adjvex);

visited[p->adjvex] = 1;

enQueue(qu, p->adjvex);

}

p = p->nextarc;

}

}

printf("\n");

}

int main ()

{

int a[4][MAXV] = {{0, 1, 1, 1},

{1, 0, 1, 1},

{1, 1, 0, 0},

{1, 1, 0, 0}};

AdjGraph* g;

CreateAdj(g, a, 4, 5);

printf("这是原始邻接表的结构: \n");

DispAdj(g);

printf("\nthis is the Deep fist search (from '0'):\n");

DFS(g, 0);

printf("\nthis is the Broad fist search (from '0): \n");

BFS(g, 0);

system("pause");

return 0;

}

原始数据

原始数据以及运行结果

记得点赞哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值