数据结构-图-深度优先遍历(DFS)

深度优先遍历(Depth_First_Search),也称为深度优先搜索,简称DFS

深度优先遍历其实就是一个递归的过程,就像一个树的前序遍历。

连通图:

        它从一个图中某个顶点V出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和V有路径相通的顶点都被访问到。

对于非连通图:

        只需要对他的连通分量分别进行深度优先遍历,即在先前一个顶点进行一次深度优先遍历后,若图中还有顶点没有被访问,则另选图中未被访问的顶点作为起始点,重复上述过程,直到图中所有顶点都被访问了为止。

引用课件图片,便于理解:

#include<stdio.h>
#include<stdlib.h>

#define INFINITY 65535              //最大值∞   会在带权的图中用到,即网
#define MAX_VERTEX_NUM 20           //图的最大顶点数
#define MAX_INFO 20                 //最大信息数
#define MAX 999

typedef char InfoType;              //附加信息类型
typedef int VRType;                 //顶点关系类型
typedef int VertexType;             //顶点数据类型
typedef enum {DG, DN, UDG, UDN} GraphKind;      //{有向图,有向网,无向图,无向网}
typedef int Boolean;                    //Boolean是布尔类型,其值是TRUE 或 FALSE
Boolean visited[MAX];                  //访问标志的数组


//-----------------------数组表示法-----------------------//
typedef struct ArcCell {
    VRType adj;     //顶点关系类型,对无权图用1或0表示是否相邻;对带权图,则为权值类型
    InfoType *info; //附加信息指针
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
 
typedef struct {
    VertexType vexs[MAX_VERTEX_NUM];//顶点向量
    AdjMatrix arcs;     //邻接矩阵
    int vexnum, arcnum;  //当前顶点数和弧数
    GraphKind kind;     //图的种类
}MGraph;



//-----------------------图的邻接表存储-----------------------//

//弧的节点结构
typedef struct ArcNode{
    int adjvex;             //该弧所指向的顶点位置
    struct ArcNode *nextarc;//指向下一条弧的指针
    InfoType *info;         //当前结点(弧)的信息
}ArcNode;
//顶点的结点结构
typedef struct VNode{
    VertexType data;//顶点信息
    ArcNode *firstarc;//指向第一个依附于该顶点弧的指针
}VNode,*AdjList[MAX_VERTEX_NUM];

typedef struct {
    AdjList vertices;
    int vexnum,arcnum;//图的当前顶点数和弧数
    int kind;        //图的种类标志
}ALGraph;



//-----------------------对邻接矩阵进行深度优先遍历-----------------------//
void VisitFunc(int v)
{
    printf("%d",v);
}

int FirstAdjVex(MGraph G, int v) {              //返回v(序号)的第一个相邻节点(序号)
    if(v > G.vexnum || v < 0)
        return -1;
    int j = 0;                                  //如果是网
    if(G.kind == DN || G.kind == UDN){
        j = INFINITY;
    }
    for(int i = 0; i < G.vexnum; i++){
        if(G.arcs[v][i].adj != j){
            return i;
        }
    }
    return -1;
}
 
int NextAdjVex(MGraph G, int v, int w) {        //w是v的相邻节点,返回v相对w的下一个节点的序号,否则返回-1
    int i, j;
    j = 0;                                      //如果为网
    if (G.kind == DN || G.kind == UDN)
        j = INFINITY;
    //两顶点不相邻
    if (G.arcs[v][w].adj == j)
        return -1;
    //从w之后的结点开始
    for (i = w + 1; i < G.vexnum; i++)
        if (G.arcs[v][i].adj != j)
            return i;
    return -1;
}

void DFS(MGraph G, int v) {                  //从第v个顶点出发递归地深度优先遍历图G
    visited[v] = 1;
    VisitFunc(G.vexs[v]);               //访问第v个顶点
    for (int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w)){
        if (!visited[w]){                    //对未访问的邻接顶点w递归调用DFS
            DFS(G, w);
        }
    }
}
 
void DFSTraverse(MGraph G) {                //对图G做深度优先遍历
    for (int i = 0; i < G.vexnum; ++i) {
        visited[i] = 0;   //访问标志数组初始化
    }
    for (int j = 0; j < G.vexnum; ++j) {
        if (!visited[j])
            DFS(G, j);   //对未访问的顶点调用DFS
    }
}




//邻接表为存储结构的图进行深度优先遍历
void DFSAL(ALGraph *G,int i)            //以Vi为出发点对邻接表存储的图G进行DFS搜索
{
    ArcNode *p;
    VisitFunc(G->vertices[i]->data);
    visited[i] = true;                  //标记Vi已访问

    p = G->vertices[i]->firstarc;         //取Vi边表的头指针

    while(p)                            //依次搜索Vi的临界点Vj,j=p->adjvex
    {
        if(!visited[p->adjvex])
        {
            DFSAL(G,p->adjvex);
            p=p->nextarc;               //找Vi的下一个邻接点
        }
    }
}

void DFSTraverse(ALGraph *G) {                //对图G做深度优先遍历
    for (int i = 0; i < G->vexnum; ++i) {
        visited[i] = 0;   //访问标志数组初始化
    }
    for (int j = 0; j < G->vexnum; ++j) {
        if (!visited[j])
            DFSAL(G, j);   //对未访问的顶点调用DFS
    }
}


//建立图的邻接表结构
void CreateALGraph(ALGraph *G)
{
    ArcNode *e;
    printf("请输入顶点数和边数:\n");
    scanf("%d,%d",&G->vexnum,&G->arcnum);    //输入顶点数和边数
    for(int i=0;i<G->vexnum;i++)
    {
        scanf("%d",&G->vertices[i]->data);            //输入顶点信息
        G->vertices[i]->firstarc = NULL;             //将边表置为空表
    }
    for(int k=0;k<G->arcnum;k++)
    {
        int i,j;
        printf("输入边(vi,vj)上的顶点序号:\n");
        scanf("%d,%d",&i,&j);                       //输入边(vi,vj)上的顶点序号
        e = (ArcNode*)malloc(sizeof(ArcNode));      //向内存申请空间,生成边表结点
        e->adjvex = j;                              //邻接序号为j
        e->nextarc = G->vertices[i]->firstarc=e;        //将e指针指向当前顶点指向的结点
        G->vertices[i]->firstarc = e;                //将当前顶点的指针指向e
        e = (ArcNode*)malloc(sizeof(ArcNode));      //向内存申请空间,生成边表节点
        e->adjvex =i;                               //邻接序号为i
        e->nextarc = G->vertices[j]->firstarc;          //将e指针指向当前顶点指向的结点
        G->vertices[j]->firstarc =e;                 //将当前顶点的指针指向e
    }
}

int main() {
    ALGraph *G;
    G=(ALGraph*)malloc(sizeof(ALGraph));
    CreateALGraph(G);
    DFSTraverse(G);
    return 0;
}

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是C++创建数据结构以及深度优先的介绍和演示: 1. 创建数据结构 在C++中,我们可以使用邻接矩阵或邻接表来表示。邻接矩阵是一个二维数组,其中每个元素表示两个顶点之间是否有边。邻接表则是由每个顶点的邻接点列表组成的数组。每个邻接点列表包含与该顶点相邻的所有顶点。 下面是使用邻接表表示的C++代码示例: ```c++ #include <iostream> #include <vector> using namespace std; // 邻接点结构体 struct AdjNode { int v; // 相邻顶点的下标 AdjNode* next; // 指向下一个邻接点的指针 AdjNode(int _v) : v(_v), next(nullptr) {} }; // 顶点结构体 struct Vertex { char data; // 顶点数据 AdjNode* first; // 指向第一个邻接点的指针 Vertex(char _data) : data(_data), first(nullptr) {} }; // 结构体 struct Graph { vector<Vertex> Vex; // 顶点数组 int vexNum; // 顶点数 int edgeNum; // 边数 Graph(int n) : vexNum(n), edgeNum(0) { Vex.resize(n); } }; // 添加边 void addEdge(Graph& G, int u, int v) { AdjNode* node = new AdjNode(v); node->next = G.Vex[u].first; G.Vex[u].first = node; G.edgeNum++; } // 创建 Graph createGraph() { int n, m; cout << "请输入顶点数和边数:"; cin >> n >> m; Graph G(n); cout << "请输入每个顶点的数据:"; for (int i = 0; i < n; i++) { char data; cin >> data; G.Vex[i] = Vertex(data); } cout << "请输入每条边的起点和终点(下标从0开始):" << endl; for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; addEdge(G, u, v); addEdge(G, v, u); // 无向需要添加反向边 } return G; } ``` 2. 深度优先 深度优先是一种递归算法,它从的某个顶点开始遍,沿着一条路径访问未访问过的顶点,直到到达最后一个顶点,然后回溯到前一个顶点,继续访问其他未访问过的顶点,直到所有顶点都被访问过。 下面是使用邻接表表示深度优先的C++代码示例: ```c++ // 深度优先 void DFS(Graph G, int v, vector<bool>& vis) { cout << G.Vex[v].data << "\t"; // 输出或存储 vis[v] = true; AdjNode* p = G.Vex[v].first; while (p) { int w = p->v; if (!vis[w]) { DFS(G, w, vis); } p = p->next; } } // 深度优先入口 void DFSTraverse(Graph G) { vector<bool> vis(G.vexNum, false); // 标记数组,记录每个顶点是否被访问过 cout << "深度优先结果:" << endl; for (int i = 0; i < G.vexNum; i++) { if (!vis[i]) { DFS(G, i, vis); } } cout << endl; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.一夜知秋.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值