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


                              图的实现:邻接表

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

    顶点节点


    边节点


    直接看代码

    类定义

    #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 << "输入每条边的起点和终点:
    ";
    		for (int k = 0; k < numEdge; k++)
    		{
    			cin >> i >> j;
    			while (!check(i, j))
    			{
    				cout << "输入的边不正确!又一次输入
    ";
    				cin >> i >> j;
    			}
    			insertEdge(i, j);
    		}
    	}
    	else  //有权图
    	{
    		cout << "输入每条边的起点、终点和权值:
    ";
    		for (int k = 0; k < numEdge; k++)
    		{
    			cin >> i >> j >> w;
    			while (!check(i, j, w))
    			{
    				cout << "输入的边不正确!又一次输入
    ";
    				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 << "输入的边不正确!又一次输入
    ";
    			cin >> tail >> head;
    		}
    		insertEdge(tail, head);
    	}
    	else  //有权图
    	{
    		while (!check(tail, head, weight))
    		{
    			cout << "输入的边不正确!又一次输入
    ";
    			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


    若有所帮助,顶一个哦!


    专栏文件夹:


  • 相关阅读:
    mysql8下载安装及配置
    jdk11下载安装及环境变量配置
    展示所有商品案例
    事务(转账实例)
    Part2.7 ESLint
    Part2.6 Webpack
    Part2.5 模块化开发
    Part2.4 gulp 实践
    Part2.3 Grunt
    Part2.2 plop 使用
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4509750.html
Copyright © 2020-2023  润新知