邻接表/图/DFS/BFS

目录

存储形式

 采用邻接表法创建无向网

邻接表的特点 

 邻接矩阵与邻接表表示法的关系

完整代码


 

 

存储形式

顶点的结构

typedef struct VNode
{
	VerTexType data;   //顶点信息
	ArcNode* firstarc; //指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum]; //AdjList表示邻接表类型

 此处AdjList v相当于VNode v[MVNum]

 弧(边)的结点结构

#define MVNum 100    //最大顶点数
typedef struct ArcNode  //边结点
{
	int adjvex;      //该边所指向的顶点的位置
	struct ArcNode* nextarc;  //指向下一条边的指针
	Otherinfo info;  //和边相关的信息
}ArcNode;

图的结构定义

typedef struct
{
	AdjList vertices;//vertices--vertex的复数
	int vexnum, arcnum; //图的当前顶点数和弧数
}ALGraph;

邻接表操作举例说明

 采用邻接表法创建无向网

Status CreateUDG(ALGraph& G)//采用邻接表表示法,创建无向图G
{
	int v1, v2,i,j;
	cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
	for (int i = 0; i < G.vexnum; ++i)  //输入各点,构造表头结点表
	{
		cin >> G.vertices[i].data;  //输入顶点值
		G.vertices[i].firstarc = NULL; //初始化表头结点的指针域
	}
	for (int k = 0; k < G.arcnum; ++k)//输入各边,构造邻接表
	{
		cin >> v1 >> v2;       //输入一条边依附的两个顶点
		i = LocateVex(G, v1);
		j = LocateVex(G, v2);

		p1 = new ArcNode;      //生成一个新的结点*p1
		p1->adjvex = k;        //邻接点序号为j
		p1->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = p1;//将新结点*p1插入顶点vi的边表头部

		p2 = new ArcNode;      //生成另一个对称的新的边结点*p2
		p2->adjvex = i;        //邻接点序号为i
		p2->nextarc = G.vertices[j].firstarc;
		G.vertices[j].firstarc = p2;  //将新结点*p2插入顶点vj的边表头部
	}
    return OK;
}

 建立有向网时候后面四行可以省略,只建立出度的即可;只留下面四行,省略上面四行,只建立入度边,可以建立逆邻接矩阵

邻接表的特点 

 邻接矩阵与邻接表表示法的关系

 

完整代码

#include <iostream>
using namespace std;

//边表结点机构,一个adjvex用来存储邻接点的位置,一个next指针用来指向下一个结点
typedef struct EdgeNode
{
	int adjvex;
	struct EdgeNode* next;
}EdgeNode;

//顶点表结点结构,data来存储数据,一个firstedge是用来指向边表的第一个结点
typedef struct
{
	string data;
	EdgeNode* firstedge;
}AdjList;

//里面的adjList[15]表示给顶点表开了15的单位大小,然后numVertex,numEdge是一个图的顶点数和边数
typedef struct
{
	AdjList adjList[15];
	int numVertex, numEdge;
}GraphAdjList;

//遍历图的顶点,返回该顶点的下标
int local(GraphAdjList G, string val)
{
	for (int i = 0; i < G.numVertex; i++)
	{
		if (G.adjList[i].data == val)
			return i;
	}
	return -1;
}

//创建邻接表
void CreateGraph(GraphAdjList& G)
{
	int i, j, k;
	string v1, v2;
	EdgeNode* e, * p, * q;
	cout << "请输入顶点数和边数,并以空格隔开:" << endl;
	cin >> G.numVertex >> G.numEdge;
	cout << "请输入顶点的信息:" << endl;
	for (i = 0; i < G.numVertex; i++)
	{
		cout << "第" << i + 1 << "个顶点:" << endl;
		cin >> G.adjList[i].data;
		G.adjList->firstedge = NULL;
	}
	for (k = 0; k < G.numEdge; k++)
	{
		cout << "请输入(vi,vj)上的顶点信息:" << endl;
		cin >> v1 >> v2;
		i = local(G,v1);
		j = local(G,v2);

		if (G.adjList[i].firstedge == NULL)
		{
			e = new EdgeNode;
			e->adjvex = j;
			e->next = NULL;
			G.adjList[i].firstedge = e;
		}
		else
		{
			p = G.adjList[i].firstedge;
			while (p->next != NULL)
			{
				p = p->next;
			}
			e = new EdgeNode;
			e->adjvex = j;
			e->next = NULL;
			p->next = e;
		}
		if (G.adjList[j].firstedge == NULL)
		{
			e = new EdgeNode;
			e->adjvex = i;
			e->next = NULL;
			G.adjList[j].firstedge = e;
		}
		else
		{
			p = G.adjList[j].firstedge;
			while (p->next != NULL)
			{
				p = p->next;
			}
			e = new EdgeNode;
			e->adjvex = i;
			e->next = NULL;
			p->next = e;
		}
	}
}

//打印邻接表
void Prin(GraphAdjList G)
{
	cout << "所建立的邻接表如下所示:" << endl;
	for (int i = 0; i < G.numVertex; i++)
	{
		cout << G.adjList[i].data;//先输出顶点信息
		EdgeNode* e = G.adjList[i].firstedge;
		while (e)
		{
			cout << "-->" << e->adjvex;
			e = e->next;
		}
		cout << endl;
	}
}

//状态数组
bool DFSvisited[50];//用于深度的标记数组
bool BFSvisited[50];//用于广搜的标记数组

//深度优先搜索
void DFS(GraphAdjList G, int i)
{
	EdgeNode* p;
	DFSvisited[i] = true;
	cout << G.adjList[i].data << "  ";
	p = G.adjList[i].firstedge;
	while (p)
	{
		if (!DFSvisited[p->adjvex])
			DFS(G.p->adjvex);
		p = p->next;
	}
}
void DFSTraverse(GraphAdjList G)
{
	for (int i = 0; i < G.numVertex; i++)
		DFSvisited[i] = false;
	for (int i = 0; i < G.numVertex; i++)
	{
		if (!DFSvisited[i])
			DFS(G, i);
	}
}

//广度优先搜索
//把相应STL中queue的操作替换掉就可以了
void BFSTraverse(GraphAdjList G)
{
	EdgeNdoe* p;
	queue<int>q;
	for (int i = 0; i < G.numVertex; i++)
		BFSvisited[i] = false;
	for (int i = 0; i < G.numVertex; i++)
	{
		if (!BFSvisited[i])
		{
			BFSvisited[i] = true;
			cout<<G.adjList[i].data << "  ";
			q.push(i);
			while (!q.empty())
			{
				int count = q.front();
				q.pop();
				p = G.adjList[count].firstedge;
				while (p)
				{
					if (!BFSvisited[p->adjvex])
					{
						BFSvisited[p->adjvex] = true;
						cout << G.adjList[p->adjvex].data << "  ";
						q.push(p->adjvex);
					}
					p = p->next;
				}
			}
		}
	}
}

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
邻接表是一种常用的存储结构,可以用来实现的遍历算法。下面是C++实现邻接表BFSDFS遍历算法的示例代码: ```c++ #include <iostream> #include <queue> using namespace std; const int MAXN = 100; bool vis[MAXN]; // 记录节点是否被访问过 // 邻接表结构体 struct Edge { int to; // 边的终点 int next; // 指向下一个邻接点的指针 } edges[MAXN * MAXN]; int head[MAXN], cnt; // head[i]表示以i为起点的第一条边的编号,cnt为边数 // 添加一条从u到v的边 void addEdge(int u, int v) { edges[++cnt].to = v; edges[cnt].next = head[u]; head[u] = cnt; } // BFS遍历 void bfs(int u) { queue<int> q; q.push(u); vis[u] = true; while (!q.empty()) { int x = q.front(); q.pop(); cout << x << " "; for (int i = head[x]; i; i = edges[i].next) { int y = edges[i].to; if (!vis[y]) { q.push(y); vis[y] = true; } } } } // DFS遍历 void dfs(int u) { vis[u] = true; cout << u << " "; for (int i = head[u]; i; i = edges[i].next) { int v = edges[i].to; if (!vis[v]) { dfs(v); } } } int main() { int n, m; cin >> n >> m; // n个节点,m条边 for (int i = 1; i <= m; i++) { int u, v; cin >> u >> v; addEdge(u, v); addEdge(v, u); // 无向需要添加反向边 } cout << "BFS遍历结果:"; bfs(1); cout << endl; memset(vis, false, sizeof(vis)); cout << "DFS遍历结果:"; dfs(1); cout << endl; return 0; } ``` 其中,`vis`数组用于记录每个节点是否被访问过,`head`数组用于记录以每个节点为起点的第一条边的编号,`cnt`表示边数。在添加边时,需要同时添加反向边,因为本例中是无向BFS遍历使用了队列,DFS遍历使用了递归。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值