数据结构之无向图邻接表DFS之查询遍历关节点(参考整理严蔚敏数据结构)

#include<iostream>
using namespace std;
#define MAXVEX 100
typedef char VType;
typedef struct ArcNode
{
	int adjvex;
	ArcNode *pNextArc;
}ArcNode;

typedef struct VexNode
{
	VType data;
	ArcNode *pFirstArc;
}VexNode;

typedef struct
{
	VexNode VLnode[MAXVEX];
	int Vnums;
	int Anums;
}ALGraph;

void CreateGraph(ALGraph &G)
{
	int i, j, k;
	ArcNode *pA;
	cin >> G.Vnums >> G.Anums;
	for (i = 0; i < G.Vnums; ++i)
	{
		cin >> G.VLnode[i].data;
		G.VLnode[i].pFirstArc = NULL;
	}
	for (k = 0; k < G.Anums; ++k)
	{
		cin >> i >> j;
		pA = new ArcNode;
		pA->adjvex = i;
		pA->pNextArc = G.VLnode[j].pFirstArc;
		G.VLnode[j].pFirstArc = pA;
		pA = new ArcNode;
		pA->adjvex = j;
		pA->pNextArc = G.VLnode[i].pFirstArc;
		G.VLnode[i].pFirstArc = pA;
	}
}

void DestroyGraph(ALGraph &G)
{
	int i;
	ArcNode *p, *q;
	for (i = 0; i < G.Vnums; ++i)
	{
		p = G.VLnode[i].pFirstArc;
		while (p)
		{
			q = p->pNextArc;
			delete p;
			p = q;
		}
	}
	G.Anums = 0;
}

int LocateVex(ALGraph G, VexNode v)
{
	int i;
	for (i = 0; i < G.Vnums; ++i)
		if (G.VLnode[i].data = v.data)
			return i;
	return -1;
}

VType GetVex(ALGraph G, int i)
{
	if (i >= G.Vnums || i < 0)
		exit(-1);
	return G.VLnode[i].data;
}

bool PutVex(ALGraph &G, int i, VType value)
{
	i = LocateVex(G, G.VLnode[i]);
	if (i > -1)
	{
		G.VLnode[i].data = value;
		return true;
	}
	else
		return false;
}

int FirstAdjVex(ALGraph G, VexNode v)
{
	int i;
	ArcNode *pA;
	i = LocateVex(G, v);
	pA = G.VLnode[i].pFirstArc;
	if (pA)
		return pA->adjvex;
	else
		return -1;
}

int NextAdjVex(ALGraph G, VexNode v, VexNode w)
{
	int i, j;
	ArcNode *pA;
	i = LocateVex(G, v);
	j = LocateVex(G, w);
	pA = G.VLnode[i].pFirstArc;
	while (pA&&pA->adjvex != j)
		pA = pA->pNextArc;
	if (!pA || !(pA->pNextArc))
		return -1;
	else
	{
		pA = pA->pNextArc;
		return pA->adjvex;
	}

}

void InsertVex(ALGraph &G, VexNode v)
{
	G.VLnode[G.Vnums].data = v.data;
	G.VLnode[G.Vnums].pFirstArc = NULL;
	G.Vnums++;
}

bool DeleteVex(ALGraph &G, VexNode v)
{
	int i, j;
	ArcNode *p, *q = NULL;
	j = LocateVex(G, v);
	if (j < 0)
		return false;
	p = G.VLnode[j].pFirstArc;
	while (p)
	{
		q = p;
		p = p->pNextArc;
		delete q;
		G.Anums--;
	}
	G.Vnums--;
	for (i = j; i < G.Vnums; ++i)
	{
		G.VLnode[i] = G.VLnode[i + 1];
	}
	for (i = 0; i < G.Vnums; ++i)
	{
		p = G.VLnode[i].pFirstArc;
		while (p)
		{
			if (p->adjvex == j)
			{
				if (p == G.VLnode[i].pFirstArc)
				{
					G.VLnode[i].pFirstArc = p->pNextArc;
					delete p;
				}
				else
				{
					q->pNextArc = p->pNextArc;
					delete p;
					p = q->pNextArc;
				}
			}
			else
			{
				if (p->adjvex>j)
					p->adjvex--;
				q = p;
				p = p->pNextArc;
			}
		}
	}
	return true;
}

bool InsertArc(ALGraph &G, VexNode v, VexNode w)
{
	ArcNode *pA;
	int i, j;
	i = LocateVex(G, v);
	j = LocateVex(G, w);
	if (i < 0 || j < 0)
		return false;
	G.Anums++;
	pA = new ArcNode;
	pA->adjvex = i;
	pA->pNextArc = G.VLnode[j].pFirstArc;
	G.VLnode[j].pFirstArc = pA;
	pA = new ArcNode;
	pA->adjvex = j;
	pA->pNextArc = G.VLnode[i].pFirstArc;
	G.VLnode[i].pFirstArc = pA;
	return true;
}

bool DeleteArc(ALGraph &G, VexNode v, VexNode w)
{
	ArcNode *p, *q = NULL;
	int i, j;
	i = LocateVex(G, v);
	j = LocateVex(G, w);
	p = G.VLnode[i].pFirstArc;
	while (p&&p->adjvex != j)
	{
		q = p;
		p = p->pNextArc;
	}
	if (p&&p->adjvex == j)
	{
		if (p == G.VLnode[i].pFirstArc)
			G.VLnode[i].pFirstArc = p->pNextArc;
		else
			q->pNextArc = p->pNextArc;
		delete p;
	}
	p = G.VLnode[j].pFirstArc;
	while (p&&p->adjvex != i)
	{
		q = p;
		p = p->pNextArc;
	}
	if (p&&p->adjvex == i)
	{
		if (p == G.VLnode[j].pFirstArc)
			G.VLnode[j].pFirstArc = p->pNextArc;
		else
			q->pNextArc = p->pNextArc;
		delete p;
		G.Anums--;
	}
	return true;
}

void VisitVex(VexNode v)
{
	cout << v.data << " ";
}

void VisitArc(VexNode v, VexNode w)
{
	cout << "(" << v.data << "->" << w.data << ")" << " ";
}

void PrintGraph(ALGraph G)
{
	int i;
	ArcNode *p;
	for (i = 0; i < G.Vnums; ++i)
		VisitVex(G.VLnode[i]);
	cout << endl;
	for (i = 0; i < G.Vnums; ++i)
	{
		p = G.VLnode[i].pFirstArc;
		while (p)
		{
			VisitArc(G.VLnode[i], G.VLnode[p->adjvex]);
			p = p->pNextArc;
		}
	}
	cout << endl;
}



bool VisitTag[MAXVEX];

void DFS(ALGraph G, int i)
{
	ArcNode *p;
	VisitTag[i] = true;
	VisitVex(G.VLnode[i]);
	p = G.VLnode[i].pFirstArc;
	while (p)
	{
		if (!VisitTag[p->adjvex])
			DFS(G, p->adjvex);
		p = p->pNextArc;
	}
}

void DFSEqual(ALGraph G, int i)
{
	int j;
	VisitTag[i] = true;
	VisitVex(G.VLnode[i]);
	for (j = FirstAdjVex(G, G.VLnode[i]); j >= 0; j = NextAdjVex(G, G.VLnode[i], G.VLnode[j]))
		if (!VisitTag[j])
			DFSEqual(G, j);
}

void DFST(ALGraph G)
{
	int i;
	for (i = 0; i < G.Vnums; ++i)
		VisitTag[i] = false;
	for (i = 0; i < G.Vnums; ++i)
		if (!VisitTag[i])
			DFSEqual(G, i);//or DFSEqual(G,i);
	cout << endl;
}




#define QSIZE MAXVEX

typedef struct Queue
{
	int *pBase;
	int Front;
	int Rear;
}Queue;

void InitQueue(Queue &Q)
{
	Q.pBase = new int[QSIZE];
	Q.Front = 0;
	Q.Rear = 0;
}

bool QueueFull(Queue Q)
{
	if ((Q.Rear + 1) % QSIZE == Q.Front)
		return true;
	else
		return false;
}

bool QueueEmpty(Queue Q)
{
	if (Q.Rear == Q.Front)
		return true;
	else
		return false;
}

void EnQueue(Queue &Q, int i)
{
	if (QueueFull(Q))
		return;
	Q.pBase[Q.Rear] = i;
	Q.Rear = (Q.Rear + 1) % QSIZE;
}

void DeQueue(Queue &Q, int &i)
{
	if (QueueEmpty(Q))
		return;
	i = Q.pBase[Q.Front];
	Q.Front = (Q.Front + 1) % QSIZE;
}

void BFST(DGraph G)
{
	Queue Q;
	int i, j, k;
	InitQueue(Q);
	for (k = 0; k< G.Vnums; ++k)
		VisitTag[k] = false;
	for (k = 0; k < G.Vnums; ++k)
	{
		if (!VisitTag[k])
		{
			VisitTag[k] = true;
			VisitVex(G.VLnode[k]);
			EnQueue(Q, k);
			while (!QueueEmpty(Q))
			{
				DeQueue(Q, i);
				for (j = FirstAdjVex(G, G.VLnode[i]); j >= 0; j = NextAdjVex(G, G.VLnode[i], G.VLnode[j]))
				{
					if (!VisitTag[j])
					{
						VisitTag[j] = true;
						VisitVex(G.VLnode[j]);
						EnQueue(Q, j);
					}
				}
			}
		}
	}
	cout << endl;
}

void BFST1(ALGraph G)
{
	Queue Q;
	int i;
	ArcNode *p;
	InitQueue(Q);
	for (i = 0; i < G.Vnums; ++i)
		VisitTag[i] = false;
	for (i = 0; i < G.Vnums; ++i)
	{
		if (!VisitTag[i])
		{
			VisitTag[i] = true;
			VisitVex(G.VLnode[i]);
			EnQueue(Q, i);
			while (!QueueEmpty(Q))
			{
				DeQueue(Q, i);
				p = G.VLnode[i].pFirstArc;
				while (p)
				{
					if (!VisitTag[p->adjvex])
					{
						VisitTag[p->adjvex] = true;
						VisitVex(G.VLnode[p->adjvex]);
					}
					p = p->pNextArc;
				}
			}
		}
	}
	cout << endl;
}




int cnt;

static int low[MAXVEX];

int VisitOrder[MAXVEX];

void VisitArticul(int i, VType value)
{
	cout << "(" << i << "," << value << ") ";
}

void DFSArticul(ALGraph G, int j)
{//由findArticul()函数调用
	int k, min;
	ArcNode *p;
	VisitOrder[j] = ++cnt;
	min = VisitOrder[j];
	for (p = G.VLnode[j].pFirstArc; p; p = p->pNextArc)
	{//对j位置顶点的各个邻接点进行深度优先搜索,则成功访问到的皆为生成树上j的后代结点
		k = p->adjvex;
		if (VisitOrder[k] == 0)//没有访问的邻接点必做j的儿子
		{
			DFSArticul(G, k);//对其没有访问过的邻接点进行递归调用
			if (low[k] < min)
				min = low[k];//更新min
			if (low[k] >= VisitOrder[j])//关节点
				VisitArticul(j, G.VLnode[j].data);// 访问关节点
		}
		else//已经访问过了的邻接点或为j的祖先或者是与j有回边相通
		{
			if (VisitOrder[k] < min)//小于则替换
				min = VisitOrder[k];//更新min
		}
	}
	low[j] = min;//最终值
}

void FindArticul(ALGraph G)
{//前提必须是连通图,否则没有意义
	int i, j;
	ArcNode *p;
	cnt = 1;
	VisitOrder[0] = 1;// 设定邻接表上0号顶点为生成树的根(第一个访问的)
	low[0] = VisitOrder[0];//生成树的根结点
	for (i = 1; i < G.Vnums; ++i)
		VisitOrder[i] = 0; //其他暂未访问
	p = G.VLnode[0].pFirstArc;//从生成树根的第一个邻接点开始访问
	if (p)//为防止设置成非连通图而设定.如果是连通的话一定有邻接点,则if根本不需要
	{
		j = p->adjvex;//显然是生成树根节点在顶点序列中的位置,如果上一注释成立,则与p=G.VLnode[0].pFirstArc;直接衔接
		DFSArticul(G, j);//从第一个顶点(对应生成树的根结点)的第一个邻接点出发进行深度优先查找关节点
		                   //调用之后完成生成树的根结点的一棵子树
		if (cnt < G.Vnums)//生成树上的根有至少两棵子树,生成树的根结点为关节点
			VisitArticul(0, G.VLnode[0].data);//访问关节点
		while (p->pNextArc)//如果上一句(if语句)成立,则while一定至少执行一次;否则,则while语句一定不执行
		{//对第一个顶点(生成树的根结点)的其他邻接点进行检查
			p = p->pNextArc;
			j = p->adjvex;
			if (VisitOrder[j] == 0)
				DFSArticul(G, j);
		}
	}
}



int main(void)
{
	ALGraph G;
	CreateGraph(G);
	BFST1(G);
	DFST(G);
	PrintGraph(G);
	FindArticul(G);
	return(0);
}

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