基礎文件知識和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);
 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章