【图】BFS遍历、DFS遍历、Topology排序、判断二分性

苦逼练代码!

《【图】BFS遍历、DFS遍历、Topology排序、判断二分性》

《【图】BFS遍历、DFS遍历、Topology排序、判断二分性》

# include<stdio.h>

# include<queue>
# include<stack>
using namespace std;

# define N 103
# define M 1003

int g[N][N];
int bpG[N][N];
int visit[N];

void initG()
{
	memset(g,0,sizeof(g));
	g[1][2]=1;
	g[1][3]=1;
	g[2][1]=1;
	g[2][4]=1;
	g[2][5]=1;
	g[3][1]=1;
	g[3][6]=1;
	g[3][7]=1;
	g[4][2]=1;
	g[4][6]=1;
	g[4][8]=1;
	g[5][2]=1;
	g[5][6]=1;
	g[5][7]=1;
	g[6][3]=1;
	g[6][4]=1;
	g[6][5]=1;
	g[7][3]=1;
	g[7][5]=1;
	g[8][4]=1;

	g[9][10]=1;
	g[9][11]=1;
	g[10][9]=1;
	g[11][9]=1;
	g[11][12]=1;
	g[12][11]=1;
}

void initBiPartionG()
{
	memset(bpG,0,sizeof(bpG));
	bpG[1][2]=1;
	bpG[1][4]=1;
	bpG[2][1]=1;
	bpG[2][3]=1;
	bpG[2][5]=1;
	bpG[3][1]=1;
	bpG[3][2]=1;
	bpG[4][1]=1;
	bpG[4][7]=1;
	bpG[5][2]=1;
	bpG[5][6]=1;
	bpG[5][8]=1;
	bpG[6][5]=1;
	bpG[7][4]=1;
	bpG[7][8]=1;
	bpG[8][5]=1;
	bpG[8][7]=1;
}

void BFS(int startNode)
{
	int curNode,i,n=13;//只考虑前12个节点

	queue<int> q;
	q.push(startNode);
	visit[startNode]=1;//加入队列时就设置visit
	while(!q.empty())
	{
		curNode=q.front();
		q.pop();
		printf("%d ", curNode);
		for(i=1;i<n;i++)
		{
			if(g[curNode][i]==1 && visit[i]==0)
			{
				q.push(i);
				visit[i]=1;//加入队列时就设置visit
			}
		}
	}
}

void DFS(int startNode)
{
	int curNode,i,n=13;//只考虑前12个节点

	stack<int> s;
	s.push(startNode);
	//visit[startNode]=1;
	while(!s.empty())
	{
		curNode=s.top();
		s.pop();
		if(visit[curNode]==1)
		{
			continue;
		}
		visit[curNode]=1;//退出队列时【才需要】设置visit
		printf("%d ", curNode);
		for(i=1;i<n;i++)
		{
			if(g[curNode][i]==1 && visit[i]==0)
			{
				s.push(i);
				//visit[i]=1;
			}
		}
	}
}

void Topology()//假设小id指向大id,将无向图转换为有向图无环图(DAG)
{
	int i,j,k,n=9;//只考虑前8个节点
	int inCome[9];
	memset(inCome,0,sizeof(inCome));
	for(i=1;i<n;i++)
	{
		for(j=i+1;j<n;j++)
		{
			if(g[i][j]==1)
			{
				inCome[j]++;
			}
		}
	}
	int visit[9];
	memset(visit,0,sizeof(visit));
	for(i=1;i<n;i++)//依次找到第i个节点,方法如下:
	{
		//for(j=1;j<n;j++)//依次扫描inCome的每个元素
		for(j=n-1;j>=1;j--)//为了不让结果是1-8,我们从大id的节点开始扫描
		{
			if(inCome[j]==0 && visit[j]==0)
			{
				printf("%d ", j);
				visit[j]=1;
				for(k=1;k<n;k++)
				{
					if(g[j][k]==1)
					{
						inCome[k]--;
					}
				}
				break;
			}
		}
	}

	//正常的思路是使用队列,保存目前income=0的点,然后出一次队,邻接点的income减1,如果减1后income变为0,则入队;while(!queue.empty())。	
	printf("\n");
	memset(inCome,0,sizeof(inCome));
	for(i=1;i<n;i++)
	{
		for(j=i+1;j<n;j++)
		{
			if(g[i][j]==1)
			{
				inCome[j]++;
			}
		}
	}
	queue<int> q;
	q.push(1);
	while(!q.empty())
	{
		k=q.front();
		q.pop();
		printf("%d ", k);
		for(i=k+1;i<n;i++)
		{
			if(g[k][i]==1)
			{
				inCome[i]--;
				if(inCome[i]==0)
				{
					q.push(i);
				}
			}
		}
	}
}

void IsBiPartion(int g[][N])//本质和BFS一样,只不过要识别哪些点位于哪一层
{
	int i,j,curLevel=-1,curNode,n=9;//只考虑前8个节点
	int visitLevel[9];
	memset(visitLevel,0,sizeof(visitLevel));

	queue<int> q;
	q.push(curLevel);//增加标识层节点
	q.push(1);
	visitLevel[1]=curLevel;
	while(!q.empty())
	{
		curNode=q.front();
		q.pop();
		if(curNode<0)//当前是 标识层节点
		{
			curLevel--;//层数减1,由“-1”层变成“-2”层
			q.push(curLevel);//在队列中增加标识下一层的节点
			curNode=q.front();
			q.pop();
			if(curNode<0)//如果在一个标识层节点 后面紧跟着 另一个标识层节点,说明遍历结束
			{
				break;
			}
		}
		printf("第【%d】层==>%d\n", -visitLevel[curNode], curNode);//输出每一而node的访问层
		for(i=1;i<n;i++)
		{
			if(g[curNode][i]==1 && visitLevel[i]==0)
			{
				q.push(i);
				visitLevel[i]=curLevel;
			}
		}
	}

	//遍历所有的边,看这些边的两个端点的层数有没有都是【同奇同偶】的情况,如果有,说明set内部出现了边,表示不可二分,否则可二分
	for(i=1;i<n;i++)
	{
		for(j=i+1;j<n;j++)
		{
			if(g[i][j]==1 && (visitLevel[i]%2)==(visitLevel[j]%2))
			{
				printf("not a BiPartion graph!\n");
				return;
			}
		}
	}
	printf("is a BiPartion graph!\n");
}

int main()
{
	int i,n=13;

	initG();

	printf("BFS:\n");
	memset(visit,0,sizeof(visit));
	for(i=1;i<n;i++)
	{
		if(visit[i]==0)
		{
			BFS(i);
		}
	}
	printf("\n");

	printf("BFS:\n");
	memset(visit,0,sizeof(visit));
	for(i=1;i<n;i++)
	{
		if(visit[i]==0)
		{
			DFS(i);
		}
	}
	printf("\n");

	printf("Topology:\n");
	memset(visit,0,sizeof(visit));
	Topology();
	printf("\n");

	
	printf("IsBiPartion:\n");
	IsBiPartion(g);
	printf("\n");

	printf("IsBiPartion:\n");
	initBiPartionG();
	IsBiPartion(bpG);
	printf("\n");
	

	return 0;
}

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/mmc2015/article/details/49633571
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞