408数据结构学习笔记——图的广度优先搜索、深度优先搜索

目录

1.广度优先搜索

1.1.广度优先搜索的概念

1.2.广度优先搜索的可变性

1.3.广度优先搜索性能

2.深度优先搜索

2.1.深度优先搜索的概念

2.2.深度优先搜索的性能

3.图的遍历和图的连通性

4.王道课后题


1.广度优先搜索

1.1.广度优先搜索的概念

广度优先搜索(Breadth-First-Search, BFS),类似二叉树层次遍历。以v为起点,依次访问和v有路径相同且路径长度为1,2,……的顶点

#define MaxVertexNum 100

bool visited[MaxVertexNum];    //标记是否访问过

void BTS(Graph G, int v){    //从顶点v出发
    Queue Q;
    initQueue(Q);
    visit(v);    //访问v
    visited[v] = true;    //visited数组中下标v的元素改为true
    EnQueue(Q, v);    //v入队
    while(!IsEmpty(Q)){
        DeQueue(Q, v);    //取出队头元素
        int w;
        for(w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
            //检测所有v的邻接点
            if (!visit[w]){    //w当前未访问过
                visit(w);    //访问w
                visit[w] = true;    //visited数组中下标w的元素改为true
                EnQueue(Q, w);    //将w入队
            }//if
        }//for
    }//while
}

非连通图或非强连通图,在执行完BTS后,可能还会有剩余的顶点没有访问到,因此,要重新调用BTS函数继续进行遍历

bool visited[MaxVertexNum];

void BTS(Graph G, int v){
    visit(v);
    visited[v] = true;
    Queue Q;
    InitQueue(Q);
    EnQueue(Q, v);
    while(!IsEmpty(Q)){
        DeQueue(Q, v);
        int w;
        for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
            if (!visited[w]){
                visit(w);
                visited[w] = true;
                EnQueue(Q, W);
            }//if
        }//for
    }//while
}

void BTS_G(Graph G){
    for (int i = 0; i < G.verNum; i++) visited[i] = false;    //初始化visited数组
    //当前visited数组下标i的元素为false,调用BTS函数
    for (int i = 0; i < G.verNum; i++) if (!visited[i]) BTS(G, i);
}    

1.2.广度优先搜索的可变性

邻接矩阵唯一→广度优先遍历序列唯一

邻接表不唯一→广度优先遍历序列不唯一

1.3.广度优先搜索性能

空间复杂度:图中每个顶点都需要入队一次,最坏情况下是O(|V|)

时间复杂度:分为访问各顶点的时间和探索各条边的时间

  1. 邻接矩阵,访问V个结点,需要O(|V|),查找需遍历V行(顶点数),每行V个顶点,需要O(|V^{2}|),故时间复杂度为O(|V^{2}|)
  2. 邻接表,访问V个结点,需要O(|V|),查找E个边,需要O(|E|),故时间复杂度为O(|V|+|E|)

2.深度优先搜索

2.1.深度优先搜索的概念

首先访问起点v,然后访问与之邻接且未被访问的顶点w,再访问与w邻接且未被访问的顶点u,直到不能再继续向下访问时,依次退回到最近被访问的顶点,如果还有邻接且未被访问的顶点,则访问那个顶点,循环这个过程,直至图中所有顶点都被访问过

bool visited[MaxVertexNum];

void DFS(Graph G, int v){
    visit(v);
    visited[v] = true;
    int w;
    for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) DFS(G, w);
}

void DFS_G(Graph G){
    for (int i = 0; i < G.verNum; i++) visit[i] = false;
    for (int i = 0; i < G.verNum; i++) if (!visit[i]) DFS(G, i);
}

2.2.深度优先搜索的性能

空间复杂度:最好O(1):中间一点连着其他顶点,栈仅需一个空间;最坏O(|V|):一条线,需要全部依次压入栈中

时间复杂度:

  1. 邻接矩阵 O(|V^{2}|)
  2. 邻接表O(|V|+|E|)

3.图的遍历和图的连通性

无向图:DFS/BFS函数调用次数 = 连通分量数

有向图:起始顶点到其他顶点都有路径,则仅需一次;强连通图从任意一个顶点出发,都仅需一次

4.王道课后题

 无向图是树→连通图且没有回路 || 有 n - 1 条边的连通图

//广度搜索,对应连通图且没有回路
bool visited[MaxVertexNum];

bool IsTree(ALGraph G) {
	//初始化visited数组
	for (int i = 0; i < MaxVertexNum; i++) visited[i] = false;
	Queue Q;
	InitQueue(Q);
	//寻找图中的第一个数据
	int p;
	for (p = 0; p < MaxVertexNum; p++) if (G.vertices[p].data) break;
    int temp = p;
    int count = 0;    //标记访问了多少个顶点
	//将p入队
	EnQueue(Q, p);
	while (!IsEmpty(Q)) {
		//出队队头元素
		DeQueue(Q, p);
		//当前顶点p未扫描过,则进入标记扫描,并且找到所有与它邻接的顶点,并依次入队
		if (!visited[p]) {
			visited[p] = true;
            count++;
			for (int q = FirstNeighbor(G, p); q >= 0; q = NextNeighbor(G, p, q)){
                EnQueue(Q, q);
            }
		}
		//扫描过p,存在回路
		else return false;
	}
    //访问顶点个数不等于顶点总数,非连通图
    if (count != G.verNum) return false;
    else return true;
}
//DFS,对应有 n - 1 条边的连通图
bool visited[MaxVertexNum];

bool IsTree(ALGraph G) {
	//初始化visited数组为false
	for (int i = 0; i < G.verNum; i++) visited[i] = false;
	//vCount记录遍历顶点数,eCount记录遍历边数
	int vCount = 0, eCount = 0;
	//遍历G中的每个顶点
	for (int i = 0; i < G.verNum; i++) {
		if (!visited[i]) DFS(G, vCount, eCount, i);
	}
	//满足条件顶点数=已遍历顶点数,并且边数为n - 1
	//无向图的存储中每条边存储两次
	if (vCount == G.verNum && 2 * eCount + 2 == G.arcNum) return true;
	else return false;
}

void DFS(ALGraph G, int& vCount, int& eCount, int v) {
	if (!visited[v]) {
		visited[v] = true;
		//访问顶点数+1
		vCount++;
	}
	for (int w = FistNeighbor; w >= ; w = NextNeighbor) {
		//访问边数+1
		eCount++;
		DFS(G, vCount, eCount, w);
	}
}

#define MaxVertexNum 100

typedef struct ArcNode{
    struct ArcNode *next;
    int adjVertex;
}ArcNode;

typedef struct VNode{
    ArcNode *next;
    elemtype data;
}VNode, adjList[MaxVertexNum];

typedef struct{
    adjList vertices;
    int verNum, arcNum;
}ALGraph;

typedef struct Stack{
    int top;
    elemtype data[MaxVertexNum];
}Stack;

bool visited[MaxVertexNum];

void DFS(ALGraph G, int v){
    //初始化visited数组
    for (int i = 0; i < MaxVertexNum; i++) visited[i] = false;
    Stack S;
    InitStack(S);
    int i, j;
    //访问v,并将v压入栈中
    visited[v] = true;
    push(S, v);
    //循环直到栈空
    while(!IsEmpty(S)){
        //弹出栈顶元素
        pop(S, i);
        //访问i所有的邻接结点
        for (j = FirstNeighbor(G, i); j >= 0; j = NextNeighbor(G, i, j)){
            //将j压入栈中
            if (!visited[j]) {
                visited[j] = true;
                push(S, j);
            }
        }//for
    }//while
}

//广度搜索
#define MaxVertexNum 100

typedef struct ArcNode{
    struct ArcNode *next;
    int adjVertex;
}ArcNode;

typedef struct VNode{
    ArcNode *first;
    elemtype data;
}VNode, AdjList[MaxVertexNum];

typedef struct ALGraph{
    AdjList vertices;
    int verNum, arcNum;
}ALGraph;

typedef struct Queue{
    elemtype data[MaxVertexNum];
    int rear, front;
}Queue;

bool visited[MaxVertexNum];
bool BFS_iToj(Graph G, int i, int j){
    for (int i = 0; i < G.verNum; i++) visited[i] = false;
    Queue Q;
    InitQueue;
    EnQueue(Q, i);
    int w, v;
    while (!IsEmpty(Q)){
        DeQueue(Q, v);
        if (!visited[v]) {
            //v == j, ij存在路径,返回true
            if (j == v) return true;
            visited[v] = true;
            for (w = FistNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
                if (!visited[w]) EnQueue(Q, w);
            }
        }//if
    }//while
    //ij没有路径,返回false
    return false;
}
//深度搜索
#define MaxVertexNum 100

typedef struct ArcNode{
    struct ArcNode *next;
    int adjVertex;
 }ArcNode;

typedef struct VNode{
    ArcNode *first;
    elemtype data;
}VNode, AdjList[MaxVertexNum];

typedef struct ALGraph{
    int verNum, arcNum;
    AdjList vertices;
}ALGraph;

typedef struct Stack{
    elmetpye data[MaxVertexNum];
    int top;
}Stack;

bool visited[MaxVertexNum];

bool DFS_iToj(ALGraph G, int i, int j){
    Stack S;
    InitStack(S);
    for (int temp = 0; temp < G.verNum; temp++) visited[temp] = false;
    push(S, i);
    visited[i] = 0;
    int v, w;
    while (!IsEmpty(S)){
        pop(S, v);
        for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
            //w == j, ij存在路径,返回true
            if (w == j) return true;
            if (!visited[w]) {
                visited[w] = true;
                push(S, w);
            }
        }//for
    }//while
    return false;
}
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值