【数据结构】链式前向星存图以及DFS和BFS遍历

链式前向星

链式前向星可以说是简化版的邻接表,在做算法题的时候可以很容易的使用

她的存储结构分为两个部分,一个是边表结点,一个是顶点表结点(和邻接表非常类似)

//链式前向星的存储结构
struct edge{
    int to;     //指向那个顶点
    int next;   //同起点的下一条边的编号
    int weight; //该边的权重
} edges[MAXSIZE];

边表结点中有3个域,to是这个结点指向的那个结点值,next与该边同结点的下一条边的编号(实际上就是edges的下标)

weight是这条边的权重。

edges是一个数组,她的下标就是边的编号,也就是说我们是给边编好号的,一般从0开始编号。

int head[MAXSIZE];

顶点表结点,如果这个顶点在图中的话,那么head值就不为-1而为其第一条边的编号(当然,也就是构造图的时候以该顶点为起点的最后构造的边的编号,这个有点绕)。

加边操作

//加边操作
void addEdge(int st, int ed, int we){
    edges[sumE].to = ed;
    edges[sumE].weight = we;
    edges[sumE].next = head[st];
    head[st] = sumE++;
}

加边操作也很简单,to就是边的结束结点,weight就是权重,next为head[st],然后head[st]指向该节点,以便下一条链接或者直接作为遍历时候的第一条边。

遍历操作

链式前向星的遍历操作和书上的伪代码非常像

for(int i=head[v]; i!=-1; i=edges[i].next);

当i==-1的时候就代表已经把从v节点其实的边所对应的结点都遍历完了。

完整代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define MAXSIZE 100

//链式前向星的存储结构
struct edge{
    int to;     //指向那个顶点
    int next;   //同起点的下一条边的编号
    int weight; //该边的权重
} edges[MAXSIZE];
int head[MAXSIZE];

//将head数组初始化为-1
void InitHead(){
    memset(head, -1, sizeof(head));
}

int sumE = 0;   //边的不编号,从0开始

//加边操作
void addEdge(int st, int ed, int we){
    edges[sumE].to = ed;
    edges[sumE].weight = we;
    edges[sumE].next = head[st];
    head[st] = sumE++;
}
//遍历链式前向星结构
void Traverse(){
    for(int i=0; i<MAXSIZE; i++){
        if(head[i] != -1){
            printf("head[%d]:", i);
            for(int j=head[i]; j!=-1; j=edges[j].next){
                printf("%d ", edges[j].to);
            }
            printf("\n");
        }
    }
}

int visited[MAXSIZE];

//深度优先遍历搜索
void DFS(int);
void DFSTraverse(){
    //初始化访问数组
    for(int i=0; i<MAXSIZE; i++){
        visited[i] = 0;
    }
    for(int i=0; i<MAXSIZE; i++){
        if(head[i] != -1 && visited[i] == 0){
            DFS(i);
        }
    }
}

void DFS(int n){
    if(visited[n] == 0){
        printf(" %d ", n);
    }
    visited[n] = 1; //表示访问过了
    for(int i=head[n]; i!=-1; i=edges[i].next){
        if(!visited[edges[i].to]){
            DFS(edges[i].to);
        }
    }
}


//广度优先搜索
void BFS(int);
void BFSTraverse(){
    //初始化访问数组
    for(int i=0; i<MAXSIZE; i++){
        visited[i] = 0;
    }
    for(int i=0; i<MAXSIZE; i++){
        if(head[i] != -1 && visited[i] == 0){
            BFS(i);
        }
    }
}

void BFS(int n){
    queue<int> q;
    q.push(n);
    if(visited[n] == 0)
        printf(" %d ", n);
    visited[n] = 1;
    while(!q.empty()){
        int v = q.front();
        q.pop();
        for(int i=head[v]; i!=-1; i=edges[i].next){
            if(!visited[edges[i].to]){
                printf(" %d ", edges[i].to);
                visited[edges[i].to] = 1;
                q.push(edges[i].to);
            }
        }
    }
}

int main(){
    InitHead();
    //存图
    addEdge(1, 2, 1);
    addEdge(1, 3, 1);
    addEdge(1, 4, 1);
    addEdge(2, 4, 1);
    addEdge(2, 5, 1);
    //反向再存一遍
    addEdge(2, 1, 1);
    addEdge(3, 1, 1);
    addEdge(4, 1, 1);
    addEdge(4, 2, 1);
    addEdge(5, 2, 1);
    Traverse();
    printf("DFS: ");
    DFSTraverse();
    printf("\nBFS: ");
    BFSTraverse();
    return 0;
}

测试用的图以及最后的结果

发布了130 篇原创文章 · 获赞 151 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/haohulala/article/details/100050889
今日推荐