深度优先遍历c

1. 深度优先遍历

1. 算法框架

1. 邻接表存储的搜索算法
int visited[n];//n为结点的个数
graph head[100];//graph为邻接表存储类型
dfs(int k){//head图的顶点数组
    edgenode * ptr;//图的指针
    visited[k] = 1;
    print("访问",k);
    ptr = head[k].firstedge;
    while(ptr != null){//遍历至链表尾
       if(visited[pre->vertex] = 0){
           dfs(ptr -> vertex);//递归遍历
       	   ptr = ptr -> nextnode;//下一个顶点
       }
    }
}
2. 零阶矩阵存储的搜索算法
int visited[n];//有n个顶点
int g[n][n];
dfsm(int k){
    printf("访问",k);
    visited[k] = 1;
    for(int i = 0;i < n;i++){
        if(g[k][j] = 1 && visited[j] == 0){
            dfsm(j);
        }
    }
}

2 深度优先搜索的应用

例1:走迷宫问题
题目:
  1. 依然是利用例2的迷宫图,进行存储和解决该问题,详见广度优先遍历c
算法分析:
  1. 使用深度优先搜索,就是一直向着可同行的下一个方格走,直到搜索到出口就找到解;如果行不通则返回上一个方格(这里空想比较难理解,因为本身就在递归中,而这个题之所以可以控制返回即回溯,就是因为search中的for循环),继续搜索其他方向
  2. 数据结构设计:利用迷宫本身的存储空间,除了记录方格走过的信息,我们还要标识是否可行
  3. 实现程序
#include<stdio.h>
#define N 8
int total;
int maze[N][N] = {  {0,0,0,0,0,0,0,0},
					{0,1,1,1,1,0,1,0},
					{0,0,0,0,1,0,1,0},
					{0,1,0,0,0,0,1,0},
					{0,1,0,1,1,0,1,0},
					{0,1,0,0,0,0,1,1},
					{0,1,0,0,1,0,0,0},
					{0,1,1,1,1,1,1,0} };
int fx[4] = { -1,1,0,0 }; int fy[4] = { 0,0,-1,1 };
int check(int i, int j ,int k) {
	int flag = 1;
	i = i + fx[k]; j = j + fy[k];
	if (i < 0 || i>7 || j < 0 || j>7) {//是否在迷宫内
		flag = 0;
	}
	else if (maze[i][j] != 0) {//是否可行
		flag = 0;
	}
	return flag;
}
void Out() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (maze[i][j] == 3) {
				total++;
			}
			printf("%d ", maze[i][j]);
		}
		printf("\n");
	}
	printf("有%d步数\n", total);
	return;
}
void search(int i,int j) {
	int  newi, newj;
	for (int k = 0; k < 4; k++) {
		if (check(i,j ,k)== 1) {
			newi = i + fx[k]; newj = j + fy[k];
			maze[newi][newj] = 3;
			if (newi == 7 && newj == 7) {
				Out();
				return;
			 }
			else {
				search(newi, newj);
			}
		}
	}
	maze[i][j] = 2;//表示该点已经判断出来不可以再走了
	
	return;
}
void main() {
	total = 1;
	maze[0][0] = 3;
	search(0, 0);
	return;
}
小结:
  1. 本算法和广度优先搜索算法一样,每个方格有四个方向可以遍历,这样一个结点(方格)有可能多次成为一个活结点,而在广度优先算法中,一个结点(方格)就只有一次成为活结点,出队后就变为了死结点,不再进行操作
  2. 与过度优先算法相比,在空间效率上二者相近,都需要赋值空间
  3. 用过度有限算法最先搜索到的是一条左端路径,而用深度搜索,则可以很快的找到一条可行的路劲;但是如果要通过深搜法确保找到最短路径,则需找到所有路劲,再从中筛选出最短路径
例2:七巧板涂色问题
题目:

有如题的七巧板,试设计算法,使用至多4中不同的颜色对七巧板进行涂色,要求相邻区域的颜色互不相同,打印输出所有的可能涂色的方案

算法分析:
  1. 该例中就使用了深搜的方法

    1. 再深搜是并不加入任何涂色的策略,只是对每个顶点逐次尝试4种颜色

    2. 检查是否和其相邻结点颜色发生了冲突

    3. 如果没有发生冲突,则按一项方式继续进行试探;

      如果发生了,返回到上一个还没有尝试完4种颜色的结点

  2. 程序实现

#include<stdio.h>
//使用零阶矩阵存储七巧板
int a[7][7] = { {0,1,0,0,1,0,1},
				{1,0,0,1,0,1,0},
				{0,0,0,1,0,0,1},
				{0,1,1,0,0,1,1},
				{1,0,0,0,0,0,1},
				{0,1,0,1,0,0,0},
				{1,0,1,1,1,0,0} };
int color[7] = { 0 };//激素1~7的卡盘个图什么色号
int total;//记录有几种涂色的方法
int check(int t) {
	int flag = 0;
	//判断相邻的卡片颜色是否冲突
	for (int i = 0; i <  t; i++) {
		if (a[i][t] == 1 && color[i] == color[t] ) {
			flag = 1;
			break;
		}
	}
	return flag;
}
void Out() {
	printf("*********第%d个解决方案******\n",total+1);
	total++;
	for (int i = 0; i < 7; i++) {
		printf("第%d的颜色是%d\n", i + 1, color[i]);
		//color[i] = 0;//初始化color数组,便与下一次的搜索
	}
	return;
}
void try(int t) {
	if (t == 7) {
		//表示7个卡片已经填充完毕
		Out();
	}
	 
	else {
		for (int k = 1; k <= 4; k++) {//用1~4代表不同的颜色
			color[t] = k;
			if (check(t)==0) {//如果颜色填充不冲突
				try(t + 1);
			}
		}
	}
	return;
	
}
void main() {
	total = 0;
	try(0);//有1好开始填充颜色==枚举
	printf("total = %d", total);
	return;
}
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值