利用邻接表做存储结构对图进行深度搜索遍历和广度搜索遍历——C++

本代码中深度搜索遍历用的是递归思想。

广度为非递归思想,没办法用递归思想进行广度搜索!(个人理解,如果是大佬大话,可以尝试一下用递归思想)


#include<iostream>
using namespace std;
#include<iostream>
using namespace std;
//---图的邻接表存储表示---
#define MVNum 100	//最大顶点数
typedef string VerTexType;
typedef string OtherInfo;
//边节点中有:1.邻接点在表中的位置 2.下一个邻接点的地址 3.与边相关的信息
typedef struct ArcNode
{
	int adjvex;				//该边所指向的顶点的位置
	struct ArcNode* nextarc;//指向下一条边的指针
	OtherInfo info;			//和边相关的信息
}ArcNode;
//表头节点中有:1.与头节点相关的信息 2.第一个邻接点的地址
typedef struct VNode		//顶点信息
{
	VerTexType data;		//指向第一条依附该顶点的指针
	ArcNode* firstarc;		//ArcNode表示邻接表类型
}VNode, AdjList[MVNum];		//相当于定义了一个数组???
//图:邻接表,图的顶点数和边数
typedef struct
{
	AdjList vertices;
	int vexnum, arcnum;
}ALGraph;
//用邻接表表示法创建无向图
/*
1.输入总顶点数和总边数
2.依次输入点的信息存入顶点表中,使每个表头结点的指针域初始化为NULL
3.创建邻接表,依次输入每条边依附的两个顶点,确定这两个顶点的序号i和j之后,
将此边节点分别插入vi和vj对应的两个边链表的头部
*/
int LocateVex(ALGraph& G, char* v1)//疑问:像这种不是每个路径都有返回值对不对?
{
	for (int i = 0; i < G.vexnum; i++)
	{
		if (v1 == G.vertices[i].data)
			return i;
	}
}
void GreateUDG(ALGraph& G)
{
	int i, k, j;
	ArcNode* p1, * p2;
	string v1, v2;
	cin >> G.vexnum >> G.arcnum;		//输入顶点数和边数
	for (i = 0; i < G.vexnum; ++i)		//此处有疑问:到底在这种情况下i++和++i有没有区别?
	{									//顶点表初始化
		cin >> G.vertices[i].data;		//输入顶点表里面的数据
		G.vertices[i].firstarc = NULL;	//顶点表的指针先设为空
	}
	//加入边表正式创建邻接表
	for (k = 0; k < G.arcnum; ++k)
	{
		cin >> v1 >> v2;				//输入一条边依附的两个顶点
		i = LocateVex(G, &v1[0]);			//确定v1,v2在G中的位置,即
		j = LocateVex(G, &v2[0]);			//在表G.vertices中的序号
		p1 = new ArcNode;				//生成一个新的边节点
		p1->adjvex = j;					//邻接点序号为j
		p1->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = p1;//插入边节点
		p2 = new ArcNode;//对对应的另一个顶点表执行同样的操作
		p2->adjvex = i;
		p2->nextarc = G.vertices[j].firstarc;
		G.vertices[j].firstarc = p2;
	}
}
void show(ALGraph& G)
{
	for (int i = 0; i < G.vexnum; i++)
	{
		ArcNode* p = G.vertices[i].firstarc;//为什么指向只能是这样 
		cout << i << " " << G.vertices[i].data;
		while (p)
		{
			cout << "——>"<< p->adjvex ;
			p = p->nextarc;

		}
		cout << endl;
	}
}

//寻找v的第一个邻接点是? 
/*int First(ALGraph G,int v)
{
	ArcNode *p=G.vertices[v].firstarc,*q;
	while(p)
	{
		q=p;
		p=p->nextarc;
	}
	return q->adjvex;
}
int Next(ALGraph G,int v,int w)
{
	cout<<w<<endl;
	ArcNode *p=G.vertices[v].firstarc,*q;
	while(p->nextarc)
	{
		q=p;
		p=p->nextarc;
		if(p->adjvex==w)
			return q->adjvex;
		
	}
	
}
*/
bool visited[MVNum];//标志某点是否被访问,默认初始值为 false=0,true=1
//————递归思想———— 
void DFS(ALGraph G, int v)//v为第v个顶点 
{
	ArcNode *p;
//	cout<<"DFS"<<endl;
	int w;
	cout << G.vertices[v].data<<" ";//输出访问的点
	visited[v] = true;//将该点标志为已经访问过的点
/*	for (w = First(G, v); w >= 0; w = Next(G, v, w))//w代表——表示v的所有邻接点,Fist(G,v)代表v的第一个邻接点,Next(G,v,w)代表v相对于w的下一个邻接点
	{
	///	cout<<v<<" "<<w<<endl;
		if (!visited[w])//w未被访问,w==0
			DFS(G, w);
		}*/
	//像这种———人的思维知道怎样返回,但就是没法用具体的计算机语言说明时,用递归是非常不错的思想
	p=G.vertices[v].firstarc;//p指向首边节点 
	while(p)
	{
		w=p->adjvex;
		if(!visited[w])
			DFS(G,w);
		p=p->nextarc;
	 } 
}
#define MAXSIZE 20 
typedef struct 
{
	int *base;
	int rear;
	int front;
}Queue;
void initQueue(Queue &S)
{
	S.base=new int[MAXSIZE];//分配一个数组空间
	if(!S.base)
		exit(0);
	S.front=S.rear=0; 
 }
//???怎么判断队列是否满了? 
void enQueue(Queue &Q,int v)
{
	if((Q.rear+1)%MAXSIZE==Q.front)
	{
		cout<<"队列已满"<<endl;
		exit(0); 
	}
	Q.base[Q.rear]=v;
	Q.rear=(Q.rear+1)%MAXSIZE;//因为循环,所以取余 
}
void deQueue(Queue &Q,int &e)
{
	if(Q.front==Q.rear)
	{
		cout<<"队列已空"<<endl;
		exit(0);
	}
	e=Q.base[Q.front];
	Q.front=(Q.front+1)%MAXSIZE;//+1就+1,为什么还要% 
 } 
bool Queueempty(Queue &Q)
{
	if(Q.front==Q.rear)//空了 
		return true;
	else //非空0 
		return false;
}
//——————广度搜索非递归—————— 
bool visit[MVNum];
void BFS(ALGraph G,int v)
{
	Queue Q;
	int w,u;
	ArcNode *p;
	cout<<G.vertices[v].data<<" ";
	visit[v]=true;
	initQueue(Q);
	enQueue(Q,v);
	while(!Queueempty(Q))
	{
		deQueue(Q,u);
		p=G.vertices[u].firstarc;
		while(p)
		{
			w=p->adjvex;
			if(!visit[w])
			{
				cout<<G.vertices[w].data<<" ";
				visit[w]=true;
				enQueue(Q,w);
			}
			p=p->nextarc;
		}
	}
 } 
int main(void)
{
	string v1,v2;
	ALGraph G;
	GreateUDG(G);
	show(G);
	cout<<"输入深度搜索遍历起点:"<<endl;
	cin>>v1;
	DFS(G,LocateVex(G,&v1[0]));
	cout<<endl;
	cout<<"输入广度搜索遍历起点:"<<endl;
	cin>>v2;
	BFS(G,LocateVex(G,&v2[0])); 
}

输入实例:

/*
8 9
v1 v2 v3 v4 v5 v6 v7 v8
v1 v2
v1 v3
v2 v4
v2 v5
v4 v8
v5 v8
v3 v6
v3 v7
v6 v7
0 v1——>2——>1——>
1 v2——>4——>3——>0——>
2 v3——>6——>5——>0——>
3 v4——>7——>1——>
4 v5——>7——>1——>
5 v6——>6——>2——>
6 v7——>5——>2——>
7 v8——>4——>3——>

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

try again!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值