文件
我們知道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);
}