图的深度优先遍历(递归、非递归;邻接表,邻接矩阵)

众所周知,图有经典的两种遍历方式:深度优先遍历和广度优先遍历
首先我们就来说说深度优先遍历,其他的不说了,直接上代码,分为递归个非递归的方式啊

首先是递归的方式实现的,比较简单,考虑到存储结构由邻接矩阵和邻接表,有分为两种:一种是邻接矩阵存储的递归,简单点说就是用数组来存储;另一种是邻接表存储的,也就是说用链表的方式存储的

一、递归
1、邻接矩阵:

#include<stdio.h>
#define MAX 100

typedef struct
{
    int e[MAX][MAX];
    int ves;
    int edge;
    int book[MAX];//标志判断是否有被访问过 
}MGraph;

void createMGraph(MGraph *G)
{
    int i;
    int j;
    int start;
    int end;

    printf("please input the ves and edge:\n");
    scanf("%d %d",&G->ves,&G->edge);
//初始化
    for(i = 0; i < G->ves; i++)
    {
        for(j = 0; j < G->ves; j++)
    {
        G->e[i][j] = 0;
    }
    G->book[i] = 0;//没被访问过的结点置为0 
    }
//创建邻接矩阵 
    printf("please input the (vi,vj)\n");
    for(i = 0; i < G->edge; i++)
    {
        scanf("%d %d",&start,&end);
    G->e[start][end] = 1;
    }
}

void dfs(MGraph *G,int ves)
{
    int i;

    G->book[ves] = 1;//被访问过的结点置为1 
    printf("%d ",ves);

    for(i = 0; i < G->ves; i++)
    {
       if(G->e[ves][i] != 0 && G->book[i] == 0)
       {
           dfs(G,i);
       }
    }
} 

int main()
{
    MGraph G;
    createMGraph(&G);

    dfs(&G,0);
    return 0;
}

这里写图片描述

2、邻接表:

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

#define MAX 100

typedef struct// 边表结点
{
    int adjves;//存储顶点的下标
    struct EdgeNOde* next;//连接下一个邻点
}EdgeNode;

typedef struct VertexNode//顶点表结点
{
    int ves;//顶点的值
    EdgeNode* firstedge;//相连的顶点的值
}VertexNode,AdjList[MAX];
//邻接表
typedef struct
{
    AdjList adjlist;
    int ves;//顶点
    int edge;//边
    int book[MAX];//判断是否有被访问过
}MGraph;

void createMGraph(MGraph *G)
{
    int i;
    int start;
    int end;

    EdgeNode *e;

    printf("please input the ves and edge:\n");
    scanf("%d%d",&(G->ves),&(G->edge));
//初始化
    printf("please input the ves:\n");

    for(i = 0; i < G->ves; i++)//输入顶点
    {
        scanf("%d",&(G->adjlist[i].ves));
    G->adjlist[i].firstedge = NULL;
    }
//创建邻接矩阵

    printf("please input the edges:\n");
    for(i = 0; i < G->edge; i++)
    {
        scanf("%d%d",&start,&end);

        e =(EdgeNode*)malloc(sizeof(EdgeNode));//分配空间
    e->adjves = end;
    e->next = G->adjlist[start].firstedge;
    G->adjlist[start].firstedge = e;//类似于链表的前插


        e =(EdgeNode*)malloc(sizeof(EdgeNode));//分配空间
    e->adjves = start;
    e->next = G->adjlist[end].firstedge;
    G->adjlist[end].firstedge = e;//类似于链表的前插
    }
}

void dfs(MGraph *G,int ves)
{
    EdgeNode *p;

    G->book[ves] = 1;//被访问过的结点置为1
    printf("%d ",G->adjlist[ves].ves);
    p = G->adjlist[ves].firstedge;//取顶点

    while(p)
    {
       if(G->book[p->adjves] == 0)//未被访问过
       {
           dfs(G,p->adjves);
       }
       p = p->next;
    }
}

int main()
{
    MGraph G;
    createMGraph(&G);

    dfs(&G,0);
    return 0;
}

结果:
这里写图片描述

二、非递归:
1、邻接矩阵:
主要的思想方法:
基本的思想是:
 初始化栈
 输出起始的顶点,起始顶点改为“已访问”的标志,将起始顶点进栈
 重复一下的操作直至栈为空:
取栈顶元素顶点,存在着未被访问的邻结点W
输出顶点W,将顶点W改为“已访问”,将W进栈;
否则,当前顶点退栈

#include<iostream>
#include<stack>

#define MAX 100

using namespace std;

typedef struct
{
    int e[MAX][MAX];
    int edge;//边
    int ves;//顶点
    int book[MAX];//判断标志是否是被访问
}MGraph;

void createMGraph(MGraph* G)
{
    int i;
    int j;
    int start;
    int end;

    cout<<"please input the ves and edge:"<<endl;
    cin>>G->ves>>G->edge;

    //初始化
    for(i = 0; i < G->ves; i++)
    {
        for(j = 0; j < G->ves; j++)
    {
        G->e[i][j] = 0;
    }
    G->book[i] = 0;//标识全部置0,表示没有访问过结点
    }
    //创建邻接矩阵
    cout<<"please input the edge(vi,vj)\n"<<endl;
    for(i = 0; i < G->edge; i++)
    {
        cin>>start>>end;
    G->e[start][end] = 1;
    }
}
void dfs(MGraph* G,int ves)
{
   stack<int> s;//创建一个栈
   cout<<ves;

   G->book[ves] = 1;//已经访问过结点ves了
   s.push(ves);//入栈

   while(!s.empty())
   {
       int data;
       int i;

       data =s.top();//取top的顶点
       for(i = 0; i < G->ves; i++)
       {
           if(G->e[data][i] != 0 && G->book[i] != 1)
       {
           cout<<i ;//访问
           G->book[i] = 1;
           s.push(i);
           break;
       }
       }
       if(i == G->ves)//data相邻的结点都访问结束了,就弹出data
       {
           s.pop();
       }
   }
}

int main()
{
    MGraph G;
    createMGraph(&G);

    dfs(&G,0);

    return 0;
}

2、邻接表
思路过程跟邻接矩阵一样的

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

#define MAX 100

using namespace std;

struct Node// 边表结点
{
    int adjves;//存储顶点的下标
    struct Node* next;//连接下一个邻点
};

typedef struct Node EdgeNode;

typedef struct VertexNode//顶点表结点
{
    int ves;//顶点的值
    EdgeNode* firstedge;//相连的顶点的值
}VertexNode,AdjList[MAX];

typedef struct
{
    AdjList adjlist;//邻接表
    int ves;//顶点
    int edge;//边
    int book[MAX];//判断是否有被访问过
}MGraph;

void createMGraph(MGraph *G)
{
    int i;
    int start;
    int end;

    EdgeNode *e;

    cout<<"please input the ves and edge:"<<endl;
    cin>>G->ves>>G->edge;
//初始化
    cout<<"please input the ves:"<<endl;

    for(i = 0; i < G->ves; i++)//输入顶点
    {
        cin>>G->adjlist[i].ves;
    G->adjlist[i].firstedge = NULL;
    }
//创建邻接矩阵

    cout<<"please input the edges:"<<endl;;
    for(i = 0; i < G->edge; i++)
    {
        cin>>start>>end;

        e =(EdgeNode*)malloc(sizeof(EdgeNode));//分配空间
    e->adjves = end;
    e->next = G->adjlist[start].firstedge;
    G->adjlist[start].firstedge = e;//类似于链表的前插

        e =(EdgeNode*)malloc(sizeof(EdgeNode));//分配空间
    e->adjves = start;
    e->next = G->adjlist[end].firstedge;
    G->adjlist[end].firstedge = e;//类似于链表的前插
    }
}

void dfs(MGraph *G,int i)
{
    stack <int>s;  
    EdgeNode *p;

    memset(G->book,0,sizeof(G->book));//清空标志位

    G->book[i]=1;  
    s.push(i);  
    cout<<G->adjlist[i].ves;

    p = G->adjlist[i].firstedge; 
    while(!s.empty())  
    {  
        p = G->adjlist[s.top()].firstedge; 
        while(p)  
        {  
            if(G->book[p->adjves] == 0) 
        {                              
            G->book[p->adjves]=1;  
                printf("%d",G->adjlist[p->adjves].ves);  

                s.push(p->adjves); 
        p = G->adjlist[p->adjves].firstedge; 
            }  
            else  
                 p=p->next;  
         }
         if(p == NULL)
     {
             s.pop();  
     }
     }   
}

int main()
{
    MGraph G;
    createMGraph(&G);

    dfs(&G,0);
    return 0;
}

结果:
这里写图片描述

  • 36
    点赞
  • 201
    收藏
  • 打赏
    打赏
  • 8
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 8

打赏作者

zjq_smile

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值