数据结构:图的实现--邻接表

数据结构与算法 同时被 2 个专栏收录
50 篇文章 0 订阅
49 篇文章 63 订阅

                          图的实现:邻接表

当图中的边数较少时,用邻接表来实现图结构,则会浪费很多内存空间。因此,考虑另一种实现图结构的方法:邻接表。在邻接表中主要有两种节点结构体:

顶点节点


边节点


直接看代码

类定义

#include<iostream>
#include<iomanip>
using namespace std;
//最大权值
#define MAXWEIGHT 100
//边节点
typedef struct edgenode_tag
{
	int adjvex;  //邻接点
	int weight;  //边的权值
	struct edgenode_tag *next;
}EdgeNode;
//顶点节点
typedef struct vertex_tag
{
	int vertex;   //顶点
	EdgeNode *next;
}Vertex;
class Graph
{
private:
	//是否带权
	bool isWeighted;
	//是否有向
	bool isDirected;
	//顶点数
	int numV;
	//边数
	int numE;
	//邻接表
	Vertex *adjList;
public:
	/*
	构造方法
	numV是顶点数,isWeighted是否带权值,isDirected是否有方向
	*/
	Graph(int numV, bool isWeighted = false, bool isDirected = false);
	//建图
	void createGraph();
	//析构方法
	~Graph();
	//获取顶点数
	int getVerNums()
	{return numV;}
	//获取边数
	int getEdgeNums()
	{return numE;}
	//插入边
	void insertEdge(int tail, int head, int weight = 1);
	void insertedge(int tail, int head, int weight);
	//设置指定边的权值
	void setEdgeWeight(int tail, int head, int weight);
	//打印邻接表
	void printAdjacentList();
	//检查输入
	bool check(int tail, int head, int weight = 1);
};

类实现

/*
构造方法
numV是顶点数,isWeighted是否带权值,isDirected是否有方向
*/
Graph::Graph(int numV, bool isWeighted, bool isDirected)
{
	while (numV <= 0)
	{
		cout << "输入的顶点数不正确!,重新输入 ";
		cin >> numV;
	}
	this->numV = numV;
	this->isWeighted = isWeighted;
	this->isDirected = isDirected;
	//边数初始化为0
	numE = 0;
	adjList = new Vertex[numV];  //指针数组
	for (int i = 0; i < numV; i++)
	{
		adjList[i].vertex = i;
		adjList[i].next = NULL;
	}
}
//建图
void Graph::createGraph()
{
	//用一个新的变量表示边数,numE的修改则留到insertedge()中
	int numEdge = 0;
	cout << "输入边数 ";
	while (cin >> numEdge && numEdge < 0)
		cout << "输入有误!,重新输入 ";

	int i, j, w;
	if (!isWeighted)  //无权图
	{
		cout << "输入每条边的起点和终点:\n";
		for (int k = 0; k < numEdge; k++)
		{
			cin >> i >> j;
			while (!check(i, j))
			{
				cout << "输入的边不对!重新输入\n";
				cin >> i >> j;
			}
			insertEdge(i, j);
		}
	}
	else  //有权图
	{
		cout << "输入每条边的起点、终点和权值:\n";
		for (int k = 0; k < numEdge; k++)
		{
			cin >> i >> j >> w;
			while (!check(i, j, w))
			{
				cout << "输入的边不对!重新输入\n";
				cin >> i >> j >> w;
			}
			insertEdge(i, j, w);
		}
	}
}
//析构方法
Graph::~Graph()
{
	int i;
	EdgeNode *p, *q;
	for (i = 0; i < numV; i++)
	{
		if (adjList[i].next)
		{
			p = adjList[i].next;
			while (p)
			{
				q = p->next;
				delete p;
				p = q;
			}
		}
	}
	delete[]adjList;
}
//设置指定边的权值
void Graph::setEdgeWeight(int tail, int head, int weight)
{
	if (!isWeighted)  //无权图
	{
		while (!check(tail, head))
		{
			cout << "输入的边不对!重新输入\n";
			cin >> tail >> head;
		}
		insertEdge(tail, head);
	}
	else  //有权图
	{
		while (!check(tail, head, weight))
		{
			cout << "输入的边不对!重新输入\n";
			cin >> tail >> head >> weight;
		}
		insertEdge(tail, head, weight);
	}
}
//插入边
void Graph::insertEdge(int vertex, int adjvex, int weight)
{
	insertedge(vertex, adjvex, weight);
	if (!isDirected)  //无向图
		insertedge(adjvex, vertex, weight);
}
void Graph::insertedge(int vertex, int adjvex, int weight)
{
	EdgeNode *p, *q, *r;
	p = q = r = NULL;
	if (adjList[vertex].next)   //非第一个节点
	{
		p = adjList[vertex].next;
		//移动p到合适位置
		while (p && (p->adjvex < adjvex))
		{
			q = p;
			p = p->next;
		}
		if (p && (p->adjvex == adjvex))  //修改已有边权值
			p->weight = weight;
		else
		{
			r = new EdgeNode;
			r->adjvex = adjvex;
			r->weight = weight;
			r->next = p;
			//当加入的新节点位于表的第一个位置
			if (adjList[vertex].next == p)
				adjList[vertex].next = r;
			else
				q->next = r;
			numE++;
		}
	}
	else
	{
		p = new EdgeNode;
		p->adjvex = adjvex;
		p->weight = weight;
		p->next = NULL;
		adjList[vertex].next = p;
		numE++;
	}
}
//输入检查
bool Graph::check(int tail, int head, int weight)
{
	if (tail >= 0 && tail < numV && head >= 0 && head < numV 
		&& weight > 0 && weight <= MAXWEIGHT)
		return true;
	else
		return false;
}
//打印邻接表
void Graph::printAdjacentList()
{
	int i;
	EdgeNode *edge = NULL;
	for (i = 0; i < numV; i++)
	{
		edge = adjList[i].next;
		if (edge) //为什么加一个if判断?跟后面的换行有关。若某顶点无邻接点(无边),则会空出一行
		{
			while (edge)
			{
				cout << "w(" << i << "," << edge->adjvex << ")=" << edge->weight << "  ";
				edge = edge->next;
			}
			cout << endl;
		}
	}
}
主函数

int main(void)
{
	cout << "******使用邻接表实现图结构***by David***" << endl;
	bool isDirected, isWeighted;
	int numV;
	cout << "建图" << endl;
	cout << "输入顶点数 ";
	cin >> numV;
	cout << "边是否带权值,0(不带) or 1(带) ";
	cin >> isWeighted;
	cout << "是否是有向图,0(无向) or 1(有向) ";
	cin >> isDirected;
	Graph graph(numV, isWeighted, isDirected);
	cout << "这是一个";
	isDirected ? cout << "有向、" : cout << "无向、";
	isWeighted ? cout << "有权图" << endl : cout << "无权图" << endl;
	graph.createGraph();
	cout << "打印邻接表" << endl;
	graph.printAdjacentList();
	cout << endl;
	int tail, head, weight;
	cout << "修改指定边的权值" << endl;
	if (isWeighted)  //针对有权图
	{
		cout << "输入边的起点、终点和权值 ";
		cin >> tail >> head >> weight;
		graph.setEdgeWeight(tail, head, weight);
	}
	else  //针对无权图
	{
		cout << "输入边的起点、终点 ";
		cin >> tail >> head;
		graph.setEdgeWeight(tail, head, 1);
	}
	cout << "修改成功!" << endl;
	cout << "打印邻接矩阵" << endl;
	graph.printAdjacentList();
	system("pause");
	return 0;
}
运行


邻接表




完整代码下载:图的实现:邻接表


转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/38323593


若有所帮助,顶一个哦!


专栏目录:


  • 7
    点赞
  • 4
    评论
  • 11
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值