【数据结构】图 - 邻接表表示法

版权声明:转载请与博主联系:https://blog.csdn.net/t11383 https://blog.csdn.net/t11383/article/details/89073767

 1、邻接表表示法的基本思想:

       对图中的每个顶点vi都分别建立一个对应的单链表(对无向图称为“边表”,对有向图称为“出边表”)来存储所有邻接与顶点vi的边(对于有向图而言是指以vi为尾的弧),边表中的每个结点分别对应于邻接于顶点vi的一条边。边表中的每个结点主要包含两个域,其中邻接点域(adjvex)指示与顶点vi邻接的点在图中的位置,链域(nextedge)指示下一条边或弧的结点。如果是带权图,还可以再加一个域weight,表示从vi到adjvex这条边的权值。

       对于图中的所有顶点信息,用一个一维数组(称为“顶点表”)来存放。对于顶点表中的每个顶点单元,需要存放:该顶点信息值(data)、一个指向由邻接于该顶点的所有的边组成的边表的头指针(firstedge)。

       如下图所示:

2、代码描述:

       ALGraph.h文件: 

#pragma once

#ifndef _ALGRAPH_H_
#define _ALGRAPH_H_

#include <vector>
#include <iostream>

using namespace std;

struct EdgeNode				//出边表的结点结构类型
{
	int adjvex;				//该边的终点位置
	int weight;				//边的权值
	EdgeNode* nextedge;		//指向下一条边的指针
};

struct VexNode				//顶点表的元素结构类型
{
	char data;				//顶点信息
	EdgeNode* firstedge;	//指向该顶点对应的出边表的指针
};

class ALGraph
{
public:
	ALGraph(vector<char> vexs, int n, int e);	//构造函数
	void DFSTraverse();							//深度优先遍历图
private:
	int vexnum;
	int edgenum;							//顶点数、边数
	vector<VexNode> adjlist;				//顶点表 - 存储图中的所有顶点信息
	void DFS(int v, bool* visited);			//连通图的深度优先遍历
        void DFS(int v, bool* visited);			//连通图的深度优先遍历
};

#endif

        ALGraph.cpp文件:

#include "ALGraph.h"

/*
有向图的邻接表建立算法:
	参数vexs为存储各顶点值的数组,参数 n 和 e 分别为顶点数和边数
*/
ALGraph::ALGraph(vector<char> vexs, int n, int e)
{
	vexnum = n;
	edgenum = e;							//确定图的顶点个数和边数
	adjlist.resize(vexnum);

	//初始化顶点表
	for (int i = 0; i < vexnum; ++i)
	{
		adjlist[i].data = vexs[i];
		adjlist[i].firstedge = 0;
	}

	//依次输入所有的边的信息
	EdgeNode* p;
	for (int j = 0; j < edgenum; ++j)
	{
		int va, vb, w;
		cin >> va >> vb >> w;					//输入一条边邻接的两个顶点的序号
		p = new EdgeNode;						//产生第一个表结点
		p->adjvex = vb;
		p->weight = w;
		p->nextedge = adjlist[va].firstedge;		//插在表头
		adjlist[va].firstedge = p;
	}
}

/*
连通图的深度优先遍历递归算法
*/
void ALGraph::DFS(int v, bool* visited)
{
	cout << adjlist[v].data << endl;	//访问第v的顶点
	visited[v] = true;			//设置访问标志为true(已访问)

	EdgeNode* p = adjlist[v].firstedge;
	while (p)
	{
		int i = p->adjvex;
		if (!visited[i])
		{
			DFS(i, visited);
		}
		p = p->nextedge;
	}

	return;
}

/*
图的深度优先遍历递归算法
*/
void ALGraph::DFSTraverse()
{
	bool* visited = new bool[vexnum];		//建立访问标记数组
	for (int v = 0; v < vexnum; ++v)
	{
		visited[v] = false;					//初始化访问标记数组(未访问)
	}
	for (int v = 0; v < vexnum; ++v)
	{
		if (!visited[v])
		{
			DFS(v, visited);
		}
	}

	delete []visited;

	return;
}

/*
拓扑排序
*/
void ALGraph::TopoSort()
{
	int* indegree = new int[vexnum];		//存放各顶点入度的数组
	SeqQueue<int, 20> s;					//存储所有入度为0的顶点

	for (int i = 0; i < vexnum; ++i)
	{
		indegree[i] = 0;
	}

	EdgeNode* p;
	for (int i = 0; i < vexnum; ++i)		//求所有顶点的入度
	{
		p = adjlist[i].firstedge;
		for (; p; p = p->nextedge)
		{
			++(indegree[p->adjvex]);
		}
	}

	for (int i = 0; i < vexnum; ++i)		//使入度为0的顶点入队
	{
		if (!indegree[i])
		{
			s.EnQueue(i);
		}
	}
	
	while (!s.Empty())
	{
		int i = s.DeQueue();				//出队
		cout << adjlist[i].data;			//输出顶点
		p = adjlist[i].firstedge;
		for (; p; p = p->nextedge)
		{
			--(indegree[p->adjvex]);
			if (!indegree[p->adjvex])
			{
				s.EnQueue(p->adjvex);
			}
		}
	}

	delete[]indegree;
}

       test.cpp文件:

/*
多段图中的最短路径问题
*/

#include <iostream>
#include <vector>
#include "ALGraph.h"

using namespace std;

int main()
{
	//建立多段图
	int n, e;		//n为顶点数,e为边数
	cin >> n >> e;

	vector<char> vexs;		//顶点表
	for (int i = 0; i < n; ++i)
	{
		char temp;
		cin >> temp;
		vexs.push_back(temp);
	}

	ALGraph ms(vexs, n, e);		//建立一个有向图

	ms.DFSTraverse();
        ms.TopoSort();

	return 0;
}

3、测试:

深度遍历
拓扑排序

猜你喜欢

转载自blog.csdn.net/t11383/article/details/89073767