基础文件知识和BFS、DFS递归与非递归算法

文件
我们知道fopen(“文件名和文件储存的类别”,”以什么形态展开”);
比如fopen(“xxx.txt”,”r”);

因为我们知道fopen,如果文件打开成功则返回一个文件的指针,可以用这个指针进行读取数据如果没有打开则返回NULL;

所以用指针来接fopen;
FILE *fp;
打开文件时fscanf(fp,“所在文件的数据格式”,你想将数组存到的地方);
比如
fscanf(fp,"%s %s %s %lf %lf\n",student[i].number,student[i].name,student[i].sex,&student[i].Escore,&student[i].Mscore);

最后关闭文件
fclose(fp);

大体模型是:

*FILE fp;
fp=fopen(“xxx.txt”,”r”);
if(fp)
{
for(int i=0;i<b;i++)//b行
fscanf(fp,”%d %f\n”,&data,&num);
}
else
{
printf(“文件无法打开\n”);
}

图的dfs递归遍历:

#include<stdio.h> 
#include<stdlib.h>
const int maxn=20;
int n,color[maxn],tt,f[maxn],g[maxn];
int Map[maxn][maxn];
//这个点已经被访问过了-1;这个点还没有被访问过-2;这个点正在被访问-3; 
void initMap(int n)
{
	for(int i = 0 ;i < n ; i++)
	for(int j = 0 ;j < n ; j++)
	{
		Map[i][j]=0;
	}
}
void dfs_visit(int u)
{
	color[u]=3;
	f[u]=++tt;
	for(int i = 0; i < n; i++)
	{
		if(Map[u][i] == 0)continue;
		else{
			if(color[i] == 2)dfs_visit(i);
		}
	}
	color[u]=1;
	g[u]=++tt;
	
}
void dfs()
{
	int u;
	for(u = 0; u < n; u++)
	{
		color[u]=2;
	}
	tt=0;
	for(u = 0; u < n; u++)
	{
		if(color[u]==2)dfs_visit(u); 
	}
	for(u = 0; u < n; u++)
	{
		printf("%d : 最开始被访问的时候: %d 结束访问的时候: %d\n",u+1,f[u],g[u]);
	}
}
int main ()
{

	int p,t,q;
	printf("亲~输入图的顶点个数:\n");
	scanf("%d", &n);
	initMap(n);
	printf("这个顶点是谁?它的小伙伴有几个鸭~\n");
	for(int i = 0 ; i < n ; i++)
	{
	
		scanf("%d %d",&q,&t);
		q--;
		for(int j = 0 ; j < t ; j++)
		{
			scanf("%d", &p);
			p--;
			Map[q][p]=1;				
		}
	}
	dfs();
 } 

非递归遍历(利用栈~)
图的非递归遍历和递归遍历的步骤差不多 main函数和dfs函数都可以不变

因为main函数进行的是邻接表变成邻接矩阵,dfs进行的是初始化标记数组color[maxn]和对n个顶点的逐个dfs。
但dfs_visit函数不递归,即栈:
首先将第一个点进入栈中并将它标记为正在使用。然后用while(!(s.empty()))进行操作:首先看栈顶元素的所连元素是否存在,所以需要一个next(i)函数查看并返回,先不管它。
1.如果next返回的有值则那个值入栈,初始数组和标记color数组改变。
2.如果next返回无值则s.pop(),栈顶元素出栈,结束数组和标记color数组改变。
即让第一个点的所有邻接点入栈。为什么呐~
因为虽然我们从纸上看算法是如图二叉树先序遍历一个一个来的,但是在计算机语言里却需要把第一个的邻接点全部入栈在进行,否则的话无法将一个个遍历连接起来。这个我们画一个邻接矩阵会好理解点:
在这里插入图片描述
下面是非递归栈的代码

int next(int q)
{
	for(int i=0;i<n;i++)
	{
		
		if(Map[q][i]==1&&color[i]==2)
		{
			return i;
		}
	}
	return 31;
}
void dfs_visit(int u)
{
	stack<int>s;
	int p,q;
	s.push(u);
	color[u]== 3;
	f[u]=++tt;
	while( !(s.empty()) )
	{
		q = s.top();
		p = next(q); 
		if(p!=31)
		{
			if(color[p]==2)
			{
				color[p] = 3;
				f[p]=++tt; 
				s.push(p);
			}
		}
		else{
			s.pop();
			color[q]=1;
			g[q]=++tt; 
		}
	}
	
 } 

BFS
利用队列,队列的特点是:后进先出,所以先一个元素进队立刻出队,然后找这个元素的所有邻接点并依次入队,然后前面的front指针所指出队,其邻接点依次在之后入队,然后重复;

#include<iostream>
#include<algorithm>
using namespace std;
#include<queue>
const int maxn=50;
const int mini=99;
int Map[maxn][maxn],d[maxn];
int n;
void initmap(int n)
{
	for(int i=0;i<n;i++)
	for(int j=0; j<n ;j++)
	Map[i][j]=0;
}
void bfs(int u)
{
	queue<int >s;
	
	for(int i=0;i<n;i++)
	d[i]= mini;
	int p,q;
	d[u]=0;
	s.push(u);
	while(!(s.empty())) 
	{
		p=s.front();
		s.pop();
		for(int z=0;z<n;z++)
	    {
	    	if(Map[p][z]==0)continue;
	    	if(d[z]!=mini)continue;
	    	d[z]=d[p]+1;
	    	s.push(z);
	    //	printf("liliilili\n");
		}
		//printf("wawawawawa\n");
	}
	for(int j=0;j<n;j++)
	{
		printf("%d %d \n",j+1,d[j]);
	 } 
}
int main()
{
	int q,p,k;
	scanf("%d",&n);
	initmap(n);
	for(int i=0;i<n;i++)
	{
		scanf("%d%d",&q,&k);
		q--;
		for(int j =0 ;j < k; j++)
		{
			scanf("%d",&p);
			p--;
			Map[q][p]=1;
		}
	}
	bfs(0);
 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章