1. 程式人生 > >樹與圖的遍歷 學習記錄

樹與圖的遍歷 學習記錄

樹與圖的深度優先遍歷,樹的DFS序、深度和重心

DFS

//深度優先遍歷 dfs 
void dfs(int x)
{
	v[x]=1;//記錄點x被訪問過,v是visit的縮寫 
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i];
		if (v[y]) continue;//點y已經被訪問過了 
		dfs(y);
	}
}

樹的DFS序

//樹的DFS序
void dfs(int x)
{
	a[++m]=x;//a陣列儲存DFS序 
	v[x]=1;//記錄點x被訪問過 
	for (int i=head[x];i;i=Next[
i]) { int y=ver[i]; if (v[y]) continue; dfs(y); } a[++m]=x; }

樹的深度

//樹的深度
void dfs(int x)
{
	v[x]=1;
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i];
		if (v[y]) continue;
		d[y]=d[x]+1;//從父節點x到子節點y遞推,計算深度 
		dfs(y);
	}
}

樹的重心

//樹的重心
void dfs(int x)
{
	v[x]=1;//子樹x的大小 
	size[x]=1;
	int
max_part=0;//刪掉x後分成的最大子樹的大小 for (int i=head[x];i;i=Next[i]) { int y=ver[i]; if (v[y]) continue;//點y已經被訪問過了 dfs(y); size[x]+=size[y];//從子節點向父節點遞推 max_part=max(max_part,size[y]); } max_part=max(max_part,n-size[x]);//n為整棵樹的節點數目 if (max_part<ans) { ans=max_part;//全域性變數ans記錄重心對應的max_part值
pos=x;//全域性變數pos記錄了重心 } }

圖的連通塊劃分

//圖的連通塊劃分
void dfs(int x)
{
	v[x]=cnt;
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i];
		if (v[y]) continue;
		dfs(y);
	}
	
}
for (int i=1;i<=n;++i)//在int main()中 
	if (!v[i])
	{
		++cnt;
		dfs(i);
	}

樹與圖的廣度優先遍歷,拓撲排序

BFS

void bfs()
{
	memset(d,0,sizeof(d));
	queue<int>q;
	q.push(1);
	d[1]=1;
	while (q.size()>0)
	{
		int x=q.front();
		q.pop();
		for (int i=head[x];i;i=Next[i])
		{
			int y=ver[i];
			if (d[y]) continue;
			d[y]=d[x]+1;
			q.push(y);
		}
	}
}

拓撲排序

void add(int x,int y)//在鄰接表中新增一條有向邊 
{
	ver[++len]=y,Next[len]=head[x],head[x]=len;
	deg[y]++;
}
void topsort()//拓撲排序 
{
	queue<int>q;
	for (int i=1;i<=n;++i)
		if (!deg[i]) q.push(i);
	while (q.size())
	{
		int x=q.front();
		q.pop();
		a[++cnt]=x;
		for (int i=head[x];i;i=Next[i])
		{
			int y=ver[i];
			if (--deg[y]==0) q.push(y);
		}
	}
}
int main()
{
	cin>>n>>m;//點數、邊數 
	for (int i=1;i<=m;++i)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
	}
	topsort();
	for (int i=1;i<=cnt;++i)
		printf("%d ",a[i]);
	printf("\n");
}