图的遍历--学习笔记

图 

图就是右4一些小圆点(称为顶点)和连接这些小圆点的直线(称为边)组成的。

图的遍历有两种方式,什么是遍历呢?遍历就是把每一个顶点都访问一次。每个顶点的访问顺序,称为时间戳。

图分为有向图和无向图,如果给图的每一边规定一个方向,那么得到的图称为有向图,其边称为有向边。在有向图中,与一个点关联的边有出边和入边之分,而与一个有向边关联的两个点也有始点和终点之分。相反没有方向的图称为无向图。

 

 

这就是一个图,无向图。

图的遍历有两种方式:

1.深度优先搜索

2.广度优先搜索

深度优先搜索

深度优先搜索的主要思想是:首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未被访问过的顶点:当没有未被访问的顶点时,回到上一个顶点,继续试探访问其他顶点,,知道所有顶点都被访问过。

对上图用深度优先搜索,访问顺序是1->2->4->3->5

用深度优先搜索上图等同于

#include<stdio.h>
int map[100][100];
int map1[100];
int n,a,b,sum=0;
void fun(int x)
{
  printf("%d ",x);
  sum++;//计数
  if(sum==n) return ;//全部搜完了
  for(int i=1;i<=n;i++)
  {
     if(map[x][i]==1&&map1[i]==0)//还没被搜过
        {
         map1[i]=1;//标记
         fun(i);
  }
}
  
int main()
{
   int i,j;
   scanf("%d",&n);
   for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
        {  
           if(i==j)map[i][j]=0;//不存在的边
           else  map[i][j]=100;
        }
  for(i=1;i<=n;i++)
     {
        scanf("%d %d",&a,&b);
        map[a][b]=1;//因为是无向图所以两边都要
        map[b][a]=1;
     }
  map[1]=1;//标记,已经走过
  fun(1);//从顶点1开始搜索
  return 0;
}
        
   

 输入的是n和边

 

深度优先搜索一般用来求最短路程之类的

那么接下来做个题目吧

输入

第一行输入n城市总数,m公路总数;接下来输入a,b,c,代表一条公路从a到b,路程为c。

输出

从起点到终点的最短路程

 

#include<stdio.h>
int n,m,a,b,c,k;
int sum[100][100];
int sign[100];
int min=1000;
void fun(int x,int num)
{

    if(num>min) return ;//没有搜索的必要
    if(x==n)//到达
    {
        if(num<min)
            min=num;
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(sum[x][i]!=100&&sign[i]==0)
        {
            sign[i]=1;
            fun(i,sum[x][i]+num);
            sign[i]=0;//方便下一次搜索
        }
    }
    return ;
}
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
    {
        if(i==j)sum[i][j]=0;
        else sum[i][j]=100;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&a,&b,&c);
        sum[a][b]=c;
    }
    sign[1]=1;
    fun(1,0);
    printf("%d",min);
    return 0;
}

如果把图改成无向图,代码几乎差不多

只需把sum[a][b]=c;这里再加上sum[b][a]=c;

广度优先搜索

广度优先搜索的主要思想:首先以一个为被访问过的顶点作为起始顶点,访问其所有相邻的顶点,然后对每个相邻的顶点,在访问它们的相邻的未被访问过的顶点,知道所有顶点都被访问过。

对刚开始的图用广度优先搜索,访问次序是:1->2->3->5->4;

相当于下图:

 

#include<stdio.h>
int sum[100][100];
int sign[100],q[100];
int n,a,b,head,tail,x;
int main()
{
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
    {
        if(i==j)sum[i][j]=0;
        else sum[i][j]=100;
    }
    for(i=1;i<=n;i++)
    {
        scanf("%d %d",&a,&b);
        sum[a][b]=1;
        sum[b][a]=1;
    }
    sign[1]=1;
    head=tail=1;
    q[head]=1;
    tail++;
    while(head<tail)//队不为空时
    {
        x=q[head];
        for(i=1;i<=n;i++)
        {
            if(sum[x][i]==1&&sign[i]==0)
            {
                sign[i]=1;//标记
                q[tail]=i;//入队
                tail++;
            }
        }
        head++;
    }
    for(i=1;i<tail;i++)
        printf("%d ",q[i]);
    return 0;
}

 广度优先搜索一般用来求最少步数之类的

接下来,一个题目

输入

第一行输入n表示城市总数,m代表航线总数,q代表起点城市,p代表终点城市

接下来输入a,b代表a到b有一条航线

输出

最少转机次数

/*#include<stdio.h>
int sum[100][100];
int sign[100],q[100];
int n,a,b,head,tail,x;
int main()
{
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
    {
        if(i==j)sum[i][j]=0;
        else sum[i][j]=100;
    }
    for(i=1;i<=n;i++)
    {
        scanf("%d %d",&a,&b);
        sum[a][b]=1;
        sum[b][a]=1;
    }
    sign[1]=1;
    head=tail=1;
    q[head]=1;
    tail++;
    while(head<tail)//队不为空时
    {
        x=q[head];
        for(i=1;i<=n;i++)
        {
            if(sum[x][i]==1&&sign[i]==0)
            {
                sign[i]=1;//标记
                q[tail]=i;//入队
                tail++;
            }
        }
        head++;
    }
    for(i=1;i<tail;i++)
        printf("%d ",q[i]);
    return 0;
}*/



#include<stdio.h>
struct node
{
    int x;
    int sum;
}que[100];
int main()
{
    int n,m,q,p,k,y,i,j;
    int sum[100][100],sign[100];
    int head,tail;
    scanf("%d %d %d %d",&n,&m,&q,&p);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
    {
        if(i==j)sum[i][j]=0;
        else sum[i][j]=100;
    }
    for(i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        sum[a][b]=1;
        sum[b][a]=1;
    }
    head=tail=1;
    que[head].x=q;
    que[head].sum=0;
    tail++;
    sign[1]=q;
    while(head<tail)
    {
        y=que[head].x;
        for(i=1;i<=n;i++)
        {
            if(sum[y][i]!=100&&sign[i]==0)
            {
                que[tail].x=i;
                que[tail].sum=que[head].sum+1;
                tail++;
                sign[i]=1;
            }
            if(que[tail].x==p)
            {
                k=1;
                break;
            }
        }
        if(k==1)
            break;
            head++;
    }
    printf("%d",que[tail-1].sum);
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GoLang学习笔记主要包括以下几个方面: 1. 语法规则:Go语言要求按照语法规则编写代码,例如变量声明、函数定义、控制结构等。如果程序中违反了语法规则,编译器会报错。 2. 注释:Go语言中的注释有两种形式,分别是行注释和块注释。行注释使用`//`开头,块注释使用`/*`开头,`*/`结尾。注释可以提高代码的可读性。 3. 规范代码的使用:包括正确的缩进和空白、注释风格、运算符两边加空格等。同时,Go语言的代码风格推荐使用行注释进行注释整个方法和语句。 4. 常用数据结构:如数组、切片、字符串、映射(map)等。可以使用for range遍这些数据结构。 5. 循环结构:Go语言支持常见的循环结构,如for循环、while循环等。 6. 函数:Go语言中的函数使用`func`关键字定义,可以有参数和返回值。函数可以提高代码的重用性。 7. 指针:Go语言中的指针是一种特殊的变量,它存储的是另一个变量的内存地址。指针可以实现动态内存分配和引用类型。 8. 并发编程:Go语言提供了goroutine和channel两个并发编程的基本单位,可以方便地实现多线程和高并发程序。 9. 标准库:Go语言提供了丰富的标准库,涵盖了网络编程、文件操作、加密解密等多个领域,可以帮助开发者快速实现各种功能。 10. 错误处理:Go语言中的错误处理使用`defer`和`panic`两个关键字实现,可以有效地处理程序运行过程中出现的错误。 通过以上内容的学习,可以掌握Go语言的基本语法和编程思想,为进一步学习和应用Go语言打下坚实的基础。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Golang学习笔记](https://blog.csdn.net/weixin_52310067/article/details/129467041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [golang学习笔记](https://blog.csdn.net/qq_44336275/article/details/111143767)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值