第97篇 C++数据结构(七)图-领接表实现


图的详细介绍在上一篇大佬的链接处:

1.结构

实现一个领接表的图,设计的结构如下,照着这个结构,想要设计成什么样,自己改一改就行了。

#define MAXVEX 100	//图中顶点数目的最大值
type char VertexType;	//顶点类型应由用户定义
typedef int EdgeType;	//边上的权值类型应由用户定义
/*边表结点*/
typedef struct EdgeNode{
	int adjvex;	//该弧所指向的顶点的下标或者位置
	EdgeType weight;	//权值,对于非网图可以不需要
	struct EdgeNode *next;	//指向下一个邻接点
}EdgeNode;

/*顶点表结点*/
typedef struct VertexNode{
	Vertex data;	//顶点域,存储顶点信息
	EdgeNode *firstedge	//边表头指针
}VertexNode, AdjList[MAXVEX];

/*邻接表*/
typedef struct{
	AdjList adjList;
	int numVertexes, numEdges;	//图中当前顶点数和边数
}

2.实现

2.1.变量

变量名称类型属性说明
m_vertexList_VertexPtr私有点的集合
m_vertexCountsize_t私有点的数量
m_edgeCountsize_t私有边的数量

2.2.方法

方法名返回类型参数属性说明
AdjacencyListGraph()-size_t vertexCount公有传值构造
AdjacencyListGraph()-const AdjacencyListGraph& ALG公有拷贝构造
~AdjacencyListGraph()--公有析构函数
operator = ()AdjacencyListGraph&const AdjacencyListGraph& ALG公有=重载
vertexCount() constsize_t-公有返回点数
edgeCount() constsize_t-公有返回边数
setVertexName()boolint vertexIndex, _VertexType vertexName公有设置点的名称
addVertex()bool_VertexType vertexName公有添加一个点
removeVertex()bool_VertexType vertexName公有删除一个点
setEdgeValue()bool_VertexType firstVertexName, _VertexType secondeVertexName, _EdgeType value公有更改边的数据
addEdge()bool_VertexType firstVertexName, _VertexType secondeVertexName, _EdgeType value公有添加一条边
removeEdge()bool_VertexType firstVertexName, _VertexType secondeVertexName公有删除一条边
DFS()void-公有深度优先搜索(一半,外部可访问)
BFS()void-公有广度优先搜索
init()voidsize_t vertexCount初始化保护
clear()void-保护清楚(释放)
copy()voidconst AdjacencyListGraph& ALG保护复制数据
DFS()void_VertexPtr vertexList, int currVertexIndex, bool* visited保护深度优先搜索(一半,外部不可访问)

3.测试

3.1.测试代码

#include <iostream>

#include "adjacencylistgraph.h"

int main()
{
	AdjacencyListGraph<int, char> graph(8);
	for (int i = 0; i < graph.vertexCount(); i++)
	{
		graph.setVertexName(i, 'a' + i);
	}

	std::cout << "构造一个有8个点的图,点的名称为:abcdefgh" << std::endl;
	std::cout << "深度优先搜索:" << std::endl;
	graph.DFS();
	std::cout << std::endl;

	std::cout << "广度优先搜索:" << std::endl;
	graph.BFS();
	std::cout << std::endl;

	std::cout << "添加7条边:" << std::endl;
	graph.addEdge('a', 'b', 1);
	graph.addEdge('a', 'c', 1);
	graph.addEdge('b', 'd', 1);
	graph.addEdge('b', 'e', 1);
	graph.addEdge('e', 'h', 1);
	graph.addEdge('c', 'f', 1);
	graph.addEdge('c', 'g', 1);
	std::cout << "深度优先搜索:" << std::endl;
	graph.DFS();
	std::cout << std::endl;

	std::cout << "广度优先搜索:" << std::endl;
	graph.BFS();
	std::cout << std::endl;

	std::cout << "边数:" << graph.edgeCount() << std::endl;
	std::cout << "点数:" << graph.vertexCount() << std::endl;

	std::cout << "添加一个s点:" << std::endl;
	graph.addVertex('s');
	std::cout << "深度优先搜索:" << std::endl;
	graph.DFS();
	std::cout << std::endl;

	std::cout << "广度优先搜索:" << std::endl;
	graph.BFS();
	std::cout << std::endl;

	std::cout << "添加两条边:as, ds" << std::endl;
	graph.addEdge('a', 's', 1);
	graph.addEdge('d', 's', 1);
	std::cout << "深度优先搜索:" << std::endl;
	graph.DFS();
	std::cout << std::endl;

	std::cout << "广度优先搜索:" << std::endl;
	graph.BFS();
	std::cout << std::endl;

	std::cout << "删除一条边:cf" << std::endl;
	graph.removeEdge('c', 'f');
	std::cout << "深度优先搜索:" << std::endl;
	graph.DFS();
	std::cout << std::endl;

	std::cout << "广度优先搜索:" << std::endl;
	graph.BFS();
	std::cout << std::endl;

	std::cout << "删除点f:" << std::endl;
	graph.removeVertex('f');
	std::cout << "深度优先搜索:" << std::endl;
	graph.DFS();
	std::cout << std::endl;

	std::cout << "广度优先搜索:" << std::endl;
	graph.BFS();
	std::cout << std::endl;

	return 0;
}

3.2.输出结果

构造一个有8个点的图,点的名称为:abcdefgh
深度优先搜索:
a, b, c, d, e, f, g, h,
广度优先搜索:
a, b, c, d, e, f, g, h,
添加7条边:
深度优先搜索:
a, b, d, e, h, c, f, g,
广度优先搜索:
a, b, c, d, e, f, g, h,
边数:7
点数:8
添加一个s点:
深度优先搜索:
a, b, d, e, h, c, f, g, s,
广度优先搜索:
a, b, c, d, e, f, g, h, s,
添加两条边:as, ds
深度优先搜索:
a, b, d, s, e, h, c, f, g,
广度优先搜索:
a, b, c, s, d, e, f, g, h,
删除一条边:cf
深度优先搜索:
a, b, d, s, e, h, c, g, f,
广度优先搜索:
a, b, c, s, d, e, g, h, f,
删除点f:
深度优先搜索:
a, b, d, e, s, c, h, g,
广度优先搜索:
a, b, c, d, e, h, s, g,

4.实现代码

#pragma once
#ifndef _ADJACENCYLISTGRAPH_H_
#define _ADJACENCYLISTGRAPH_H_

#include <iostream>
#include <queue>

template <typename _EdgeType>
struct Edge
{
	_EdgeType m_value;
	int m_adjacency;
	Edge* m_next;

	Edge() : m_value(_EdgeType()), m_adjacency(-1), m_next(nullptr) {}
	Edge(_EdgeType value) : m_value(value), m_adjacency(-1), m_next(nullptr) {}
	Edge(_EdgeType value, Edge* next) : m_value(value), m_adjacency(-1), m_next(next) {}
	Edge(_EdgeType value, int adjacency) : m_value(value), m_adjacency(adjacency), m_next(nullptr) {}
	Edge(_EdgeType value, int adjacency, Edge* next) : m_value(value), m_adjacency(adjacency), m_next(next) {}
};

template <typename _EdgeType, typename _VertexType>
struct Vertex
{
	_VertexType m_name;
	Edge<_EdgeType>* m_firstEdge;

	Vertex() : m_name(_VertexType()), m_firstEdge(nullptr) {}
	Vertex(_VertexType name) : m_name(name), m_firstEdge(nullptr) {}
	Vertex(_VertexType name, Edge<_EdgeType>* firstEdge) : m_name(name), m_firstEdge(firstEdge) {}
};

template <typename _EdgeType, typename _VertexType>
class AdjacencyListGraph
{
	using _VertexPtr = Vertex<_EdgeType, _VertexType>*;
	using _EdgePtr = Edge<_EdgeType>*;
public:
	AdjacencyListGraph(size_t vertexCount)
	{
		init(vertexCount);
	}

	AdjacencyListGraph(const AdjacencyListGraph& ALG)
	{
		init(ALG.m_vertexCount);
		copy(ALG);
	}

	~AdjacencyListGraph()
	{
		clear();
	}

	AdjacencyListGraph& operator = (const AdjacencyListGraph& ALG)
	{
		clear();
		init(ALG.m_vertexCount);
		copy(ALG);
		return *this;
	}

	size_t vertexCount() const
	{
		return m_vertexCount;
	}

	size_t edgeCount() const
	{
		return m_edgeCount;
	}

	bool setVertexName(int vertexIndex, _VertexType vertexName)
	{
		if (vertexIndex < 0 || vertexIndex >= m_vertexCount)
		{
			return false;
		}

		int index = 0;
		while (index < m_vertexCount)
		{
			if (m_vertexList[index].m_name == vertexName)
			{
				return false;
			}

			index++;
		}

		m_vertexList[vertexIndex].m_name = vertexName;

		return true;
	}

	bool addVertex(_VertexType vertexName)
	{
		for (int i = 0; i < m_vertexCount; i++)
		{
			if (m_vertexList[i].m_name == vertexName)
			{
				return false;
			}
		}

		_VertexPtr vertexList = new Vertex<_EdgeType, _VertexType>[m_vertexCount + 1];
		for (int i = 0; i < m_vertexCount; i++)
		{
			vertexList[i] = m_vertexList[i];
		}
		vertexList[m_vertexCount].m_name = vertexName;

		delete[]m_vertexList;
		m_vertexList = vertexList;

		m_vertexCount++;

		return true;
	}

	bool removeVertex(_VertexType vertexName)
	{
		int rmIndex = 0;
		for (; rmIndex < m_vertexCount; rmIndex++)
		{
			if (m_vertexList[rmIndex].m_name == vertexName)
			{
				break;
			}
		}
		if (rmIndex == m_vertexCount)
		{
			return false;
		}

		_VertexPtr vertexList = new Vertex<_EdgeType, _VertexType>[m_vertexCount - 1];
		for (int i = 0; i < m_vertexCount - 1; i++)
		{
			if (i < rmIndex)
			{
				vertexList[i] = m_vertexList[i];
			}
			else
			{
				vertexList[i] = m_vertexList[i + 1];
			}
		}
		delete[]m_vertexList;
		m_vertexList = vertexList;

		m_vertexCount--;

		for (int index = 0; index < m_vertexCount; index++)
		{
			if (m_vertexList[index].m_firstEdge == nullptr)
			{
				continue;
			}
			else if (m_vertexList[index].m_firstEdge->m_next == nullptr)
			{
				if (m_vertexList[index].m_firstEdge->m_adjacency == rmIndex)
				{
					delete m_vertexList[index].m_firstEdge;
					m_vertexList[index].m_firstEdge = nullptr;
				}
				else
				{
					continue;
				}
			}
			else
			{
				_EdgePtr preEdge = m_vertexList[index].m_firstEdge;
				_EdgePtr currEdge = preEdge->m_next;

				if (preEdge->m_adjacency == rmIndex)
				{
					m_vertexList[index].m_firstEdge = currEdge;

					delete preEdge;
					preEdge = nullptr;
				}
				else
				{
					while (currEdge)
					{
						if (currEdge->m_adjacency == rmIndex)
						{
							preEdge->m_next = currEdge->m_next;

							delete currEdge;
							currEdge = nullptr;

							break;
						}
						preEdge = currEdge;
						currEdge = currEdge->m_next;
					}
				}
			}
		}

		return true;
	}

	bool setEdgeValue(_VertexType firstVertexName, _VertexType secondeVertexName, _EdgeType value)
	{
		//
		int firstVertexIndex = -1;
		int secondeVertexIndex = -1;
		for (int index = 0; index < m_vertexCount; index++)
		{
			if (m_vertexList[index].m_name == firstVertexName)
			{
				firstVertexIndex = index;
			}

			if (m_vertexList[index].m_name == secondeVertexName)
			{
				secondeVertexIndex = index;
			}
		}
		if (firstVertexIndex == -1 || secondeVertexIndex == -1 || firstVertexIndex == secondeVertexIndex)
		{
			return false;
		}

		//
		if (m_vertexList[firstVertexIndex].m_firstEdge == nullptr)
		{
			return false;
		}
		else
		{
			_EdgePtr firstEdge = m_vertexList[firstVertexIndex].m_firstEdge;
			while (firstEdge)
			{
				if (firstEdge->m_adjacency == secondeVertexIndex)
				{
					firstEdge->m_value = value;
					break;
				}
				firstEdge = firstEdge->m_next;
			}

			if (firstEdge == nullptr)
			{
				return false;
			}
		}

		//
		if (m_vertexList[secondeVertexIndex].m_firstEdge == nullptr)
		{
			return false;
		}
		else
		{
			_EdgePtr firstEdge = m_vertexList[secondeVertexIndex].m_firstEdge;
			while (firstEdge)
			{
				if (firstEdge->m_adjacency == firstVertexIndex)
				{
					firstEdge->m_value = value;
					break;
				}
				firstEdge = firstEdge->m_next;
			}

			if (firstEdge == nullptr)
			{
				return false;
			}
		}

		return true;
	}

	bool addEdge(_VertexType firstVertexName, _VertexType secondeVertexName, _EdgeType value)
	{
		//
		int firstVertexIndex = -1;
		int secondeVertexIndex = -1;
		for (int index = 0; index < m_vertexCount; index++)
		{
			if (m_vertexList[index].m_name == firstVertexName)
			{
				firstVertexIndex = index;
			}

			if (m_vertexList[index].m_name == secondeVertexName)
			{
				secondeVertexIndex = index;
			}
		}
		if (firstVertexIndex == -1 || secondeVertexIndex == -1 || firstVertexIndex == secondeVertexIndex)
		{
			return false;
		}

		//
		if (m_vertexList[firstVertexIndex].m_firstEdge == nullptr)
		{
			m_vertexList[firstVertexIndex].m_firstEdge = new Edge<_EdgeType>(value, secondeVertexIndex);
		}
		else
		{
			_EdgePtr firstEdge = m_vertexList[firstVertexIndex].m_firstEdge;
			while (firstEdge->m_next)
			{
				if (firstEdge->m_adjacency == secondeVertexIndex)
				{
					return false;
				}
				firstEdge = firstEdge->m_next;
			}
			if (firstEdge->m_adjacency == secondeVertexIndex)
			{
				return false;
			}
			firstEdge->m_next = new Edge<_EdgeType>(value, secondeVertexIndex);
		}

		//
		if (m_vertexList[secondeVertexIndex].m_firstEdge == nullptr)
		{
			m_vertexList[secondeVertexIndex].m_firstEdge = new Edge<_EdgeType>(value, firstVertexIndex);
		}
		else
		{
			_EdgePtr firstEdge = m_vertexList[secondeVertexIndex].m_firstEdge;
			while (firstEdge->m_next)
			{
				firstEdge = firstEdge->m_next;
			}

			firstEdge->m_next = new Edge<_EdgeType>(value, firstVertexIndex);
		}

		m_edgeCount++;

		return true;
	}

	bool removeEdge(_VertexType firstVertexName, _VertexType secondeVertexName)
	{
		//找到需要删除的点的下标
		int firstVertexIndex = -1;
		int secondeVertexIndex = -1;
		for (int index = 0; index < m_vertexCount; index++)
		{
			if (m_vertexList[index].m_name == firstVertexName)
			{
				firstVertexIndex = index;
			}

			if (m_vertexList[index].m_name == secondeVertexName)
			{
				secondeVertexIndex = index;
			}
		}
		if (firstVertexIndex == -1 || secondeVertexIndex == -1 || firstVertexIndex == secondeVertexIndex)
		{
			return false;
		}

		//
		if (m_vertexList[firstVertexIndex].m_firstEdge == nullptr)
		{
			return false;
		}
		else if (m_vertexList[firstVertexIndex].m_firstEdge->m_next == nullptr)
		{
			if (m_vertexList[firstVertexIndex].m_firstEdge->m_adjacency == secondeVertexIndex)
			{
				delete m_vertexList[firstVertexIndex].m_firstEdge;
				m_vertexList[firstVertexIndex].m_firstEdge = nullptr;
			}
			else
			{
				return false;
			}
		}
		else
		{
			_EdgePtr preEdge = m_vertexList[firstVertexIndex].m_firstEdge;
			_EdgePtr currEdge = preEdge->m_next;

			if (preEdge->m_adjacency == secondeVertexIndex)
			{
				m_vertexList[firstVertexIndex].m_firstEdge = currEdge;

				delete preEdge;
				preEdge = nullptr;
			}
			else
			{
				while (currEdge)
				{
					if (currEdge->m_adjacency == secondeVertexIndex)
					{
						preEdge->m_next = currEdge->m_next;

						delete currEdge;
						currEdge = nullptr;

						break;
					}
					preEdge = currEdge;
					currEdge = currEdge->m_next;
				}
			}
		}

		//
		if (m_vertexList[secondeVertexIndex].m_firstEdge == nullptr)
		{
			return false;
		}
		else if (m_vertexList[secondeVertexIndex].m_firstEdge->m_next == nullptr)
		{
			if (m_vertexList[secondeVertexIndex].m_firstEdge->m_adjacency == secondeVertexIndex)
			{
				delete m_vertexList[secondeVertexIndex].m_firstEdge;
				m_vertexList[secondeVertexIndex].m_firstEdge = nullptr;
			}
			else
			{
				return false;
			}
		}
		else
		{
			_EdgePtr preEdge = m_vertexList[secondeVertexIndex].m_firstEdge;
			_EdgePtr currEdge = preEdge->m_next;

			if (preEdge->m_adjacency == firstVertexIndex)
			{
				m_vertexList[secondeVertexIndex].m_firstEdge = currEdge;

				delete preEdge;
				preEdge = nullptr;
			}
			else
			{
				while (currEdge)
				{
					if (currEdge->m_adjacency == firstVertexIndex)
					{
						preEdge->m_next = currEdge->m_next;

						delete currEdge;
						currEdge = nullptr;

						break;
					}
					preEdge = currEdge;
					currEdge = currEdge->m_next;
				}
			}
		}

		m_edgeCount--;

		return true;
	}

	void DFS()
	{
		if (m_vertexCount == 0)
		{
			return;
		}

		bool* visited = new bool[m_vertexCount];
		for (int i = 0; i < m_vertexCount; i++)
		{
			visited[i] = false;
		}

		for (int i = 0; i < m_vertexCount; i++)
		{
			if (!visited[i])
			{
				DFS(m_vertexList, i, visited);
			}
		}

		delete[] visited;
		visited = nullptr;
	}

	void BFS()
	{
		if (m_vertexCount <= 0)
		{
			return;
		}

		bool* visited = new bool[m_vertexCount];
		for (int i = 0; i < m_vertexCount; i++)
		{
			visited[i] = false;
		}

		std::queue<int> vertexIndexQueue;
		for (int currIndex = 0; currIndex < m_vertexCount; currIndex++)
		{
			if (!visited[currIndex])
			{
				visited[currIndex] = true;
				std::cout << m_vertexList[currIndex].m_name << ", ";

				vertexIndexQueue.push(currIndex);
				while (!vertexIndexQueue.empty())
				{
					int vertexIndex = vertexIndexQueue.front();
					vertexIndexQueue.pop();

					_EdgePtr edge = m_vertexList[vertexIndex].m_firstEdge;
					while (edge)
					{
						if (!visited[edge->m_adjacency])
						{
							visited[edge->m_adjacency] = true;
							std::cout << m_vertexList[edge->m_adjacency].m_name << ", ";

							vertexIndexQueue.push(edge->m_adjacency);
						}

						edge = edge->m_next;
					}
				}
			}
		}
	}

protected:
	void init(size_t vertexCount)
	{
		m_vertexCount = vertexCount;
		m_edgeCount = 0;
		if (m_vertexCount == 0)
		{
			m_vertexList = nullptr;
		}
		else
		{
			m_vertexList = new Vertex<_EdgeType, _VertexType>[m_vertexCount];
		}
	}

	void clear()
	{
		if (m_vertexList == nullptr)
		{
			return;
		}

		int index = 0;
		while (index < m_vertexCount)
		{
			_EdgePtr currEdge = m_vertexList[index].m_firstEdge;
			while (currEdge != nullptr)
			{
				_EdgePtr edge = currEdge;
				currEdge = currEdge->m_next;

				delete edge;
				edge = nullptr;
			}

			index++;
		}

		delete[]m_vertexList;
		m_vertexList = nullptr;

		m_vertexCount = 0;
	}

	void copy(const AdjacencyListGraph& ALG)
	{
		
		int index = 0;
		while (index < m_vertexCount)
		{
			_EdgePtr& myCurrEdge = m_vertexList[index].m_firstEdge;
			_EdgePtr ALGCurrEdge = ALG.m_vertexList[index].m_firstEdge;
			while (ALGCurrEdge != nullptr)
			{
				myCurrEdge = new Edge<_EdgeType>(ALGCurrEdge->m_value);
				myCurrEdge = myCurrEdge->m_next;

				ALGCurrEdge = ALGCurrEdge->m_next;
			}

			m_vertexList[index].m_name = ALG.m_vertexList[index].m_name;
			
			index++;
		}
		m_edgeCount = ALG.m_edgeCount;
	}

	void DFS(_VertexPtr vertexList, int currVertexIndex, bool* visited)
	{
		std::cout << vertexList[currVertexIndex].m_name << ", ";
		visited[currVertexIndex] = true;

		_EdgePtr firstEdge = vertexList[currVertexIndex].m_firstEdge;
		while (firstEdge)
		{
			if (!visited[firstEdge->m_adjacency])
			{
				DFS(vertexList, firstEdge->m_adjacency, visited);
			}

			firstEdge = firstEdge->m_next;
		}
	}

private:
	_VertexPtr m_vertexList;
	size_t m_vertexCount;
	size_t m_edgeCount;
};

#endif // !_ADJACENCYLISTGRAPH_H_

5.总结

实现得不是很好,代码耦合度高。领接表和领接矩阵相比,感觉还是实现起来麻烦,指针确实是很麻烦得东西,但是又方便灵活。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大唐不良猿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值