数据结构与算法--图的遍历方式(深度遍历和广度遍历)

614 阅读3分钟

1. 图的深度优先遍历

深度优先搜索算法:数据结构是栈。通过将顶点存入栈中,沿着路径探索顶点,存在新的相邻顶点就去访问

邻接矩阵深度遍历思路:

1.将图的顶点和边的信息输入到图结构中
2.创建一个数组,用来标识顶点是否已经被遍历过
3.初始化数组,将数组中元素置位 False
4.选择顶点开始遍历(注意非连通图的情况)
5.进入递归,打印 i 对应的顶点信息,并将该顶点标识为已遍历
6.循环遍历边表,判断当前边表中两个顶点是否有边(arc[i][j] 是否等 1),并且当前顶点没有遍历过,则继续递归遍历

邻接矩阵深度遍历代码实现:

// 深度优先
int visited[MAXVEX];  // 访问标志的数组
void DFS(MGraph G,int i){
    // ✅ 修改标志
    visited[i] = TRUE;
    printf("%c",G.vers[i]);
    // ✅ 递归遍历
    for (int j = 0; j <= G.numNodes; j++) {
        if (G.arc[i][j] == 1 && !visited[j]) {
            DFS(G, j);
        }
    }
}
void DFSTravese(MGraph G){
    // ✅ 初始化标志数组
    for (int i = 0; i < G.numNodes; i++) {
        visited[i] = FALSE;
    }
    // ✅ 某一个顶点(防止非连通图)
    for (int i = 0; i <= G.numNodes; i++) {
        // 判断是否已经访问
        if (!visited[i]) {
            DFS(G, i);
        }
    }
}

邻接表深度遍历代码:

// 深度优先
int visited[MAXVEX];  // 访问标志的数组
void DFS(MGraph G,int i){
    // 修改标志
    visited[i] = TRUE;
    
    EdgeNode *p;
    // 打印顶点 A
    printf("%c",G.adjlist[i].data);
    
    p = G.adjlist[i].firstedge;
    
    
    while (p) {
        if (!visited[p->adj_vex_index]) {
            DFS(G, p->adj_vex_index);
        }
        p = p->next;
    }
}

void DFSTravese(MGraph G){
    // 初始化标志数组
    for (int i = 0; i < G.numNodes; i++) {
        visited[i] = FALSE;
    }
    // 某一个顶点(防止非连通图)
    for (int i = 0; i <= G.numNodes; i++) {
        // 判断是否已经访问
        if (!visited[i]) {
            DFS(G, i);
        }
    }
}

2. 图的广度优先遍历

广度优先搜索算法:数据结构是队列。通过将顶点存入队列中,最先入队列的顶点先被探索。

思路: 先把 图 旋转,看成树 1.把根节点放到队列的末尾 2.每次从队列的头部取出一个元素,检测这个元素是否有下一级,有则全部放到队尾 3.找到所有要找的元素是结束程序 4.如果遍历整个树还没有找到,结束程序。

广度优先遍历,需要用到队列,我们先定义队列的方法

// 定义队列
typedef struct {
    int data[MAXVEX];
    int front;
    int rear;
}Queue;
// 初始化
Status InitQueue(Queue *Q) {
    Q->front = 0;
    Q->rear = 0;
    return OK;
}
// 判断空
Status QueueEmpty(Queue Q) {
    if (Q.front == Q.rear) {
        return TRUE;
    }
    return FALSE;
}

//入队
Status EnQueue(Queue *Q, int e) {
    if ((Q->rear+1)%MAXVEX == Q->front) {
        return ERROR;
    }
    Q->data[Q->rear] = e;
    Q->rear = (Q->rear + 1)%MAXVEX;
    return OK;
}
// 出队
Status DeQueue(Queue *Q, int *e) {
    if (Q->front == Q->rear)            /* 队列空的判断 */
    return ERROR;
    *e = Q->data[Q->front];
    Q->front = (Q->front+1)%MAXVEX;
    return OK;
}

邻接矩阵广度优先遍历

int visited[MAXVEX]; /* 访问标志的数组 */
void BFSTraverse(MGraph G){

    Queue Q;
    InitQueue(&Q);
    
    // 将访问标志数组全部置为"未访问状态FALSE"
    for (int i = 0 ; i < G.numVertexes; i++) {
        visited[i] = FALSE;
    }
    
    // 将访问标志数组全部置为"未访问状态FALSE"
    for (int i = 0; i < G.numNodes; i++) {
        if (!visited[i]) {
            visited[i] = TRUE;
            printf("%c  ",G.vers[i]);
            
            // 入队
            EnQueue(&Q, i);
            while (!QueueEmpty(Q)) {
                // 出队
                DeQueue(&Q, &i);
                for (int j = 0; j < G.numNodes; j++) {
                    if (G.arc[i][j] == 1 && !visited[j]) {
                        visited[j] = TRUE;
                        printf("%c   ",G.vers[j]);
                        EnQueue(&Q, j);
                    }
                }
            }
        }
    }

}

邻接表广度优先遍历

int visited[MAXSIZE]; /* 访问标志的数组 */
void BFSTraverse(GraphAdjList GL){
    
    //1.创建结点
    EdgeNode *p;
    
    Queue Q;
    InitQueue(&Q);
    

    //2.将访问标志数组全部置为"未访问状态FALSE"
    for(int i = 0; i < GL->numVertexes; i++)
        visited[i] = FALSE;
    
    //3.对遍历邻接表中的每一个顶点(对于连通图只会执行1次,这个循环是针对非连通图)
    for(int i = 0 ;i < GL->numVertexes;i++){
        //4.判断当前结点是否被访问过.
        if(!visited[i]){
            visited[i] = TRUE;
            //打印顶点
            printf("%c ",GL->adjList[i].data);
            
            EnQueue(&Q, i);
            while (!QueueEmpty(Q)) {
                DeQueue(&Q, &i);
                p = GL->adjList[i].firstedge;
                while (p) {
                    //判断
                    if(!visited[p->adjvex]){
                        visited[p->adjvex] = TRUE;
                         printf("%c ",GL->adjList[p->adjvex].data);
                        EnQueue(&Q, p->adjvex);
                    }
                    p = p->next;
                }
            }
            
        }
    }
    
}