用Python或者c语言 写广度优先和深度优先搜索

用Python或者c语言 写广度优先和深度优先搜索 图(图用邻接矩阵表示)
矩阵代码如下

img

img

img

图一是BFS(广度优先搜索)在树的情况下的执行过程,从A出发,搜索A的第二层,发现有B,C,D(必须从左到右搜索),再搜索B的第二层,发现B的第二层没有元素,再搜索C的第二层,发现有E,F,放置于D后面,再搜索D的第二层,发现有G,放置于F后面,再往下搜索E,F,G,发现只有G有第二层H和I,所以最后得到:
A B C D E F G H I
图二是BFS(广度优先搜索)在图的情况下的执行过程,假设从A出发,第二层是B和C,先搜索B的第二层,发现有D,再搜索C的第二层,发现只有E了,最后D,E中只有D有第二层F,所以最后得到:
A B C D E F
⚠️:这里不可以是:A B C E D F,因为必须先搜索B的第二层再搜索C的第二层
同理以E为起始点可以得到:E C D A B F(不同的起始点的路径不同)
BFS在python中实现运用了Queue(队列)将搜索结果进行排列

DFS(深度优先搜索):
图4 DFS
图5 stack of DFS
图4是DFS(深度优先搜索)在图的情况下的执行过程,其规则是从起始点往下走,走到底再返回,直到走完所有点:
从起始点A出发->B->C->D->F(此时到底了,返回)->E->C(此时所有点都走完了)
DFS在python中实现运用了Stack(栈)将搜索结果进行堆砌:
将起始点A先放入栈->拿出A,A后可以选择走B和C->将B,C放入栈->拿出B,B之后只能走D->将D放入栈->拿出D,D之后可以走E,F->将E,F放入栈->拿出F,F之后到底了->无放入->拿出E->拿出C
最后得到 A B D F E C (不同的起始点的路径不同)

完整python代码解析
从‘A’出发:
BFS得到A B C D E F (答案不唯一)
DFS得到A B D F E C (答案不唯一)

用字典的映射去表示图2
>>> graph = {
...     'A': ['B', 'C'],
...     'B': ['A', 'C', 'D'],
...     'C': ['A', 'B', 'D', 'E'],
...     'D': ['B', 'C', 'E', 'F'],
...     'E': ['C', 'D'],
...     'F': ['D']
... }
>>> graph.keys()-------返回图上所有节点的名称,顺序不固定
dict_keys(['A', 'B', 'C', 'D', 'E', 'F'])
>>> graph['E']------看看E的连接点
['C', 'D']
1
2
3
4
5
6
7
8
9
10
11
12
13
数组可以动态加东西,用append(),动态删东西用pop()
>>> queue = []
>>> queue.append('A')---在列表末端添加元素
>>> queue.append('B')
>>> queue.append('C')
>>> queue
['A', 'B', 'C']
>>> queue.pop(0)---删除第一个元素并返回
'A'
>>> queue
['B', 'C']
>>> queue.pop()----删除最后一个元素并返回
'C'
>>> queue
['B']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'C', 'D'],
    'C': ['A', 'B', 'D', 'E'],
    'D': ['B', 'C', 'E', 'F'],
    'E': ['C', 'D'],
    'F': ['D']
}
# input一个graph和起始点s
def BFS(graph, s):
    #创建队列
    queue = []
    #将起始点s放入队列,假设起始点为‘A’
    queue.append(s)
    #set():创建一个无序不重复元素集,可进行关系测试,删除重        复数据,还可以计算交集、差集、并集
    seen = set()
    #'A'我们已经见过,放入seen
    seen.add(s)
    #当队列不是空的时候
    while len(queue) > 0:
        #将队列的第一个元素读出来,即‘A’
        vertex = queue.pop(0)
     #graph['A']就是A的相邻点:['B','C'],将其储存到nodes
        nodes = graph[vertex]
        #遍历nodes中的元素,即['B','C']
        for w in nodes:
            #如果w没见过
            if w not in seen:
                queue.append(w)
                #加入seen表示w我们看见过了
                seen.add(w)
        print(vertex)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
执行过程:
step 1:queue=[‘A’]->seen=[‘A’]->queue=[ ]->vertex=‘A’->nodes=[‘B’,‘C’]->queue=[‘B’,‘C’]->seen=[‘A’,‘B’,‘C’]->return ‘A’
step 2:vertex=‘B’->queue=[‘C’]->nodes=[‘A’, ‘C’, ‘D’]->queue=[‘C’‘D’]->seen=[‘A’,‘B’,‘C’,‘D’]->return’B’
step 3:vertex=‘C’->queue=[‘D’]->nodes=[‘A’, ‘B’, ‘D’, ‘E’]->queue=[‘D’‘E’]->seen=[‘A’,‘B’,‘C’,‘D’‘E’]->return’C’
…

"DFS的方法就是将BFS中的队列改成栈即可"
def DFS(graph, s):
    stack = []
    stack.append(s)
    seen = set()
    seen.add(s)
    while len(stack) > 0:
        vertex = stack.pop()
        nodes = graph[vertex]
        for w in nodes:
            if w not in seen:
                stack.append(w)
                seen.add(w)
        print(vertex)
print(DFS(graph, 'A'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
求最短路径问题:

求A到E的最短路径,我们用parent建一个表,表显示每个点的前一个点是哪个点,这样我们先找E的前一个点为C,C的前一个点为A,A前没有点了,因此A到E的最短路径为A->C->E

# 用字典表示S的前一个点为空
parent = {s: None}
之前w的前一个点就是vertex,因此:
parent[w] = vertex
将这两行代码加入之前的代码中:
1
2
3
4
5
完整代码为:

def BFS(graph, s):
    queue = []
    queue.append(s)
    seen = set()
    seen.add(s)
    parent = {s: None}
    while len(queue) > 0:
        vertex = queue.pop(0)
        nodes = graph[vertex]
        for w in nodes:
            if w not in seen:
                queue.append(w)
                seen.add(w)
                parent[w] = vertex
        print(vertex)
    return parent
"测试从‘E’出发"
parent = BFS(graph, 'E')
for key in parent:
    print(key, parent[key])



DFS深度优先搜索实现代码:

#include <stdio.h>
#include <stdlib.h>
#define MAXV 4

// 定义图的邻接矩阵
typedef struct {
    int verNum, egdeNum; // 顶点个数、边条数 
    char vertex[MAXV]; // 顶点 
    int matrix[MAXV][MAXV]; // 邻接矩阵 
} MGraph;

// 初始化图 
void Init_MGraph(MGraph &G) {
    G.verNum = MAXV;
    G.egdeNum = MAXV;
    G.vertex[0] = 'A';
    G.vertex[1] = 'B';
    G.vertex[2] = 'C';
    G.vertex[3] = 'D';
    // 初始化邻接矩阵
    int num[MAXV][MAXV] = {
        {0, 1, 0, 1},
        {1, 0, 1, 0},
        {0, 1, 0, 1},
        {1, 0, 1, 0}
    };
    for (int i = 0; i < MAXV; i++) {
        for (int j = 0; j < MAXV; j++) {
            G.matrix[i][j] = num[i][j];
        }
    }
}

// 寻找下一个相邻的顶点,存在则返回下标,否则返回-1 
int FindNextVertex(MGraph &G, int vexRow, int* visited) {
    if (vexRow >= G.verNum) {
        return -1;
    }
    for (int i = 0; i < G.verNum; i++) {
        if (G.matrix[vexRow][i] != 0 && !visited[i]) {
            return i;
        }
    }
    return -1;
}

// 寻找所有相邻的顶点,存在则返回下标,否则返回-1 
int* FindAllNextVertex(MGraph &G, int vexRow, int* visited) {
    if (vexRow >= G.verNum) {
        return NULL;
    }
    int* num = (int *)malloc(G.verNum * sizeof(int));
    for (int i = 0; i < G.verNum; i++) {
        if (G.matrix[vexRow][i] != 0 && !visited[i]) {
            num[i] = i;
        } else {
            num[i] = -1;
        }
    }
    return num;
}
    
// DFS深度优先搜索
void DFS_MGraph(MGraph &G, int numSeq, int *visited, int flag) {
    if (numSeq < G.verNum && !visited[numSeq]) {
        printf("当前电影: %c, 序号: %d\n", G.vertex[numSeq], numSeq);
        visited[numSeq] = 1;
        // DFS 访问下一个顶点
        if (flag) {
            int seq = FindNextVertex(G, numSeq, visited); 
            if (seq != -1) {
                DFS_MGraph(G, seq, visited, flag);
            }
        } else {
            int* seq = FindAllNextVertex(G, numSeq, visited);
            int num = 0;
            for (int i = 0; i < G.verNum; i++) {
                if(seq[i] != -1) {
                    num++;
                }
            }
            if (num) {
                printf("\n请从以下序号中选择观影顺序:\n");
                for (int i = 0; i < G.verNum; i++) {
                    if(seq[i] != -1) {
                        printf("电影序号: %d\n", seq[i]);
                    }
                }
                int seq;
                scanf("%d", &seq);
                DFS_MGraph(G, seq, visited, flag);
            }
            free(seq);
        }
    }
}
void DFS(MGraph &G, int numSeq, int flag) {
    int visited[MAXV];
    // 初始化全局变量 
    for (int i = 0; i < MAXV; i++) {
        visited[i] = 0;
    }
    DFS_MGraph(G, numSeq, visited, flag);
    for (int i = 0; i < G.verNum; i++) {
        if (!visited[i]) {
            DFS_MGraph(G, i, visited, flag);
        }
    }
}

int main() {
    MGraph G;
    Init_MGraph(G);
    
    int seq;
    // DFS访问
    printf("\n请输入开始访问的顶点序号(0-3):");
    scanf("%d", &seq); 
    DFS(G, seq, 1);
    
    // DFS看电影顺序
    printf("\n请输入要观影的序号(0-3):");
    scanf("%d", &seq); 
    DFS(G, seq, 0);
    return 0;
}

具体运行效果:

img

图的广度和深度优先路径搜索算法(python实现)‘
可以借鉴下
https://blog.csdn.net/a15608445683/article/details/125803928

首先创建邻接矩阵,邻接矩阵的样式查了百度百科:

img

img

下面的函数就用于生成这样的一个邻接矩阵:

def creat_matrix():
    nodes = ['Mary Poppins', 'The Sound of Music', 'Enchanted', 'Up', 'The Star', 'Arrival', 'Cars', 'Toy Story', 'Coco', 'Pinocchio']
    Actors = ['J.A.','C.P.','A.A.','J.R.','T.H.','K.K.','T.A.']
    Actors_Movie = [ ['Mary Poppins','The Sound of Music','Enchanted'],
                      ['The Sound of Music','Up','The Star'],
                      ['Enchanted','Arrival'],
                      ['Up','Cars','Toy Story','Coco'],
                      ['Toy Story','Pinocchio'],
                      ['The Star','Pinocchio'],
                      ['Toy Story','Cars']]
    # matrix = [[0,1,0,1,0,0,0,0,0,0],  
    #           [1,0,1,0,0,0,0,0,0,0],
    #           [0,1,0,0,0,0,0,0,0,0],
    #           [1,0,0,0,1,0,0,0,1,0],
    #           [0,0,0,1,0,1,0,0,0,1],
    #           [0,0,0,0,1,0,1,0,0,0],
    #           [0,0,0,0,0,1,0,1,1,0],
    #           [0,0,0,0,0,0,1,0,1,0],
    #           [0,0,0,1,0,0,1,1,0,1],
    #           [0,0,0,0,0,0,0,0,0,0]]

    for i in range(len(nodes)):
        Adjacency_Matrix.append([0]*len(nodes))

    # 更新顶点相邻关系
    for i in  Actors_Movie:
        for j in i:
            for k in i:
                if not k==j:
                    Adjacency_Matrix[nodes.index(j)][nodes.index(k)] = 1

    # 邻接矩阵打印测试
    # print(Adjacency_Matrix)

广搜和深搜算法的讲解我看下面有兄弟贴了链接,直接百度搜索也搜的到,这里我写了一个深搜的例子,针对这个题目的全部代码如下:

#邻接矩阵百度百科
#https://baike.baidu.com/item/%E9%82%BB%E6%8E%A5%E7%9F%A9%E9%98%B5/9796080

# 创建一个空的列表作为邻接矩阵
Adjacency_Matrix = []

# 所有可行方案存入下面的列表中
movie_out_all=[]  

def dfs(node_index,movie_list,step=1):
    """
    node_index :整数型,指当前的节点(电影) 0-9分别对应 nodes列表中的十个电影
    move_list: 一个列表,用作搜索过程中存储已列入计划的节点
    step:整数型
    """
    if step == 1:
        movie_list[step-1] = node_index
    reflash = 0
    for i in range(len(Adjacency_Matrix[node_index])):
        temp_list = movie_list[:step]
        if Adjacency_Matrix[node_index][i] != 0 and i not in temp_list:
            movie_list[step] = i
            dfs(i,movie_list,step+1)
            reflash = 1
    if reflash == 0:
        movie_list_out = movie_list[:step]
        movie_out_all.append(movie_list_out)
        print(movie_list_out)


def creat_matrix():
    nodes = ['Mary Poppins', 'The Sound of Music', 'Enchanted', 'Up', 'The Star', 'Arrival', 'Cars', 'Toy Story', 'Coco', 'Pinocchio']
    Actors = ['J.A.','C.P.','A.A.','J.R.','T.H.','K.K.','T.A.']  # 这个列表暂时没用上
    Actors_Movie = [ ['Mary Poppins','The Sound of Music','Enchanted'],
                      ['The Sound of Music','Up','The Star'],
                      ['Enchanted','Arrival'],
                      ['Up','Cars','Toy Story','Coco'],
                      ['Toy Story','Pinocchio'],
                      ['The Star','Pinocchio'],
                      ['Toy Story','Cars']]
    # matrix = [[0,1,0,1,0,0,0,0,0,0],  
    #           [1,0,1,0,0,0,0,0,0,0],
    #           [0,1,0,0,0,0,0,0,0,0],
    #           [1,0,0,0,1,0,0,0,1,0],
    #           [0,0,0,1,0,1,0,0,0,1],
    #           [0,0,0,0,1,0,1,0,0,0],
    #           [0,0,0,0,0,1,0,1,1,0],
    #           [0,0,0,0,0,0,1,0,1,0],
    #           [0,0,0,1,0,0,1,1,0,1],
    #           [0,0,0,0,0,0,0,0,0,0]]

    for i in range(len(nodes)):
        Adjacency_Matrix.append([0]*len(nodes))

    # 更新顶点相邻关系
    for i in  Actors_Movie:
        for j in i:
            for k in i:
                if not k==j:
                    Adjacency_Matrix[nodes.index(j)][nodes.index(k)] = 1

    # 邻接矩阵打印测试
    # print(Adjacency_Matrix)


if __name__ == "__main__":
    creat_matrix()  # 生成矩阵用
    movie_list=[0]*len(Adjacency_Matrix[0])  # 用于搜索过程中存储可行的节点(电影)
    index = input("请输入首先要看的电影序号(0-9):")
    dfs(int(index),movie_list)  # 深搜

    # print("所有可行的看电影规划:")
    # print(movie_out_all)

运行结果:

img

关于题目中所说的“当有多个选项时让用户选择”这一功能,请自行完善添加
代码中或有不规范的地方还望指正,有什么疑问可以继续互相交流。

python实现:

# 定义图
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

def bfs(graph, start, end):
    # 创建一个队列,用于存储需要访问的结点
    queue = []
    # 将源点加入队列
    queue.append(start)
    # 创建一个集合,用于存储已访问的结点
    visited = set()
    # 循环遍历队列
    while queue:
        # 从队列中取出队首结点
        node = queue.pop(0)
        # 判断是否到达目标点
        if node == end:
            return True
        # 将队首结点的所有相邻结点加入队列
        for neighbor in graph[node]:
            if neighbor not in visited:
                queue.append(neighbor)
                visited.add(neighbor)
    # 未找