图的算法--DFS,BFS算法

图的算法——DFS,BFS算法

1.深度优先遍历DFS

主要思路是从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底…,不断递归重复此过程,直到所有的顶点都遍历完成,它的特点是不撞南墙不回头,先走完一条路,再换一条路继续走。

实际上不管是前序遍历,还是中序遍历,亦或是后序遍历,都属于深度优先遍历。

下面为邻接矩阵的深度优先遍历

typedef char VertexType; //每个顶点数据类型为字符型 

typedef struct
{
	VertexType Vertex[VertexMax];//存放顶点元素的一维数组 
	int AdjMatrix[VertexMax][VertexMax];//邻接矩阵二维数组 
	int vexnum,arcnum;//图的顶点数和边数  
}MGraph;
void CreateUDG(MGraph *G) 
{
	int i,j;

	printf("输入顶点个数和边数:\n");
	printf("顶点数 n="); 
	scanf("%d",&G->vexnum);
	printf("边  数 e="); 
	scanf("%d",&G->arcnum);
	printf("\n"); 
	
	printf("\n");
	

	printf("输入顶点元素(无需空格隔开):");
	scanf("%s",G->Vertex);
	printf("\n");

	for(i=0;i<G->vexnum;i++) 
	 for(j=0;j<G->vexnum;j++)
	    {
	    	G->AdjMatrix[i][j]=0;
		}
	 int n,m;
	 VertexType v1,v2;
	 
	 printf("请输入边的信息:\n");
	 for(i=0;i<G->arcnum;i++)
	 {
	 	scanf(" %c%c",&v1,&v2);
	 	n=LocateVex(G,v1); 
	 	m=LocateVex(G,v2); 
	 	
	 	if(n==-1||m==-1)
		 {
		 	printf("NO This Vertex!\n");
		 	return;
		  } 
	
	   G->AdjMatrix[n][m]=1;
	   G->AdjMatrix[m][n]=1;
	 } 
}
int visited[VertexMax];//定义"标志"数组为全局变量 

void DFS(MGraph *G,int i)
{
	int j;
	
	//1.处理起始点 
	printf("%c",G->Vertex[i]);//1.输出起始结点 
	visited[i]=1;//2.将已访问的结点标志成1
	
	 //2.由起始点开始,对后续结点进行操作
	for(j=0;j<G->vexnum;j++)//依次搜索vi的邻接点 
	{
		if(G->AdjMatrix[i][j]==1&&visited[j]==0)//当满足有边且未被访问过时,递归调用去查找该邻接点 
		{
			DFS(G,j);//注意此处的G已经是指针类型,不需要再&G 
		}
	}
	
}
void DFSTraverse(MGraph *G) 
{
	int i;
	//初始化"标志"数组为0,代表未访问
	for(i=0;i<G->vexnum;i++)
	{
		visited[i]=0; 
	} 
	
	for(i=0;i<G->vexnum;i++)
	{
		if(visited[i]==0)
		{
			DFS(G,i);//注意此处的G已经是指着类型,不需要再&G 
		}
	} 
}

2.DFS应用

马踏棋盘算法(骑士周游问题)

题目要求: 一国际象棋的棋盘为8*8的方格棋盘,现将“马"放在任意指定的方格中,按照“马"走棋的规则将 “马"进行移动。要求每个方格只能进入一次,最终使得“马"走遍棋盘64个方格。

#include<stdio.h>
#include <time.h>
#define X 8
#define Y 8

int chess[X][Y];
//找到基于(x,y)的下一个可走位置
int nextxy(int *x,int *y,int count)
{
    switch(count)
    {
        case 0:
            if(*x+2<=X-1&& *y-1>=0&&chess[*x+2][*y-1]==0)
            {
                *x+=2;
                *y-=1;
                return 1;
            }
            break;
        case 1:
            if(*x+2<=X-1&& *y+1<=Y-1&&chess[*x+2][*y+1]==0)
            {
                *x+=2;
                *y+=1;
                return 1;
            }
            break;
        case 2:
            if(*x+1<=X-1&& *y-2>=0&&chess[*x+1][*y-2]==0)
            {
                *x+=1;
                *y-=2;
                return 1;
            }
            break;
        case 3:
            if(*x+1<=X-1&& *y+2<=Y-1&&chess[*x+1][*y+2]==0)
            {
                *x+=1;
                *y+=2;
                return 1;
            }
            break;
        case 4:
            if(*x-1>=0&& *y-2>=0&&chess[*x-1][*y-2]==0)
            {
                *x-=1;
                *y-=2;
                return 1;
            }
            break;
        case 5:
            if(*x-1>=0&& *y+2<=Y-1&&chess[*x-1][*y+2]==0)
            {
                *x-=1;
                *y+=2;
                return 1;
            }
            break;
        case 6:
            if(*x-2>=0&& *y-1>=0&&chess[*x-2][*y-1]==0)
            {
                *x-=2;
                *y-=1;
                return 1;
            }
            break;
        case 7:
            if(*x-2>=0&& *y+1<=Y-1&&chess[*x-2][*y+1]==0)
            {
                *x-=2;
                *y+=1;
                return 1;
            }
            break;
        default:
            break;
    }
    return 0;
}

void print()
{
    int i,j;
    for ( i = 0; i < X; i++)
    {
        for ( j = 0; j < Y; j++)
        {
            printf("%2d\t",chess[i][j]);
        }
        printf("\n");
        
    }
    printf("\n");
}
//深度优先遍历棋盘
// (x,y)为位置坐标,tag是标记变量,每走一步,tag+1
TravelChess(int x,int y,int tag)
{
    int x1=x,y1=y,flag=0,count=0;
    chess[x][y]=tag;
    if (X*Y==tag)
    {
        //打印棋盘
        print(); 
        return 1;
    }
    //找到马的下一个可走的坐标(x1,y1),如果找到flag为1,否则为0
    flag=nextxy(&x1,&y1,count);
    while (0 == flag && count<7)
    {
        count++;
        flag=nextxy(&x1,&y1,count);
    }
    
    while (flag)
    {
        if (TravelChess(x1,y1,tag+1))
        {
            return 1;
        }
        //继续找到马的下一步可走的坐标(x1,y1),如果找到flag为1,否则为0
        x1=x;
        y1=y;
        count++;

        flag=nextxy(&x1,&y1,count);
        while (0 == flag && count<7)
        {
            count++;
            flag=nextxy(&x1,&y1,count);
        }
    }
    if (0 == flag)
    {
        chess[x][y]=0;
    }
    return 0;
}

int main()
{
    int i,j;
    clock_t start,finish;//计时器

    start=clock();

    for ( i = 0; i < X; i++)
    {
        for ( j = 0; j < Y; j++)
        {
            chess[i][j]=0;
        }
    }

    if (!TravelChess(0,0,1))
    {
        printf("马踏棋盘失败\n");
    }
    finish =clock();
    printf("\n耗时%f秒\n\n",(double)(finish-start)/CLOCKS_PER_SEC);
    
    return 0;
}

3.广度优先遍历BFS

广度优先遍历,指的是从图的一个未遍历的节点出发,先遍历这个节点的相邻节点,再依次遍历每个相邻节点的相邻节点。

我们可以利用队列来实现。

基本步骤

1.设置全局变量visited数组并初始化为全0,代表所有节点均未被访问

2.设置起始点:包括对起始点进行输出、标记成已访问、入队

3.对后续结点进行操作:由起始点开始,对后续结点进行操作(输出、标记成已访问、入队)

4.循环重复2-3的操作避免有遗漏。

void BFS(MGraph *G,int i)
{
	int j;
	CyQueue q;
	create(&q);
	
    //1.设置起始点 
	printf("%c",G->Vertex[i]);//1.输出起始结点 
	visited[i]=1;//2.将已访问的结点标志成1
	EnQueue(&q,i);//3.将第一个结点入队 

    //2.由起始点开始,对后续结点进行操作 
	while(!QueueEmpty(&q))//队列非空
	{
		
		DeQueue(&q,&i);	
		for(j=0;j<G->vexnum;j++)
		{
			if(G->AdjMatrix[i][j]==1&&visited[j]==0)
			{
				printf("%c",G->Vertex[j]);//输出符合条件的顶点 
	            visited[j]=1;//设置成已访问状态1 
	            EnQueue(&q,j);//入队 
			}
		}
	} 	
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值