数据结构——图的邻接表实现

邻接矩阵需要提前预先分配空间,容易造成空间上的浪费
而且在遇到两个顶点之间没有边时,邻接矩阵是不能解决的。

邻接表的出现 是结合了数组和链表的存储方式(当然 也可以是链表+链表)
数组+链表形式的邻接表
一维数组用来存储顶点元素,每个顶点的所有邻接点构成一个线性表
在这里插入图片描述
特点:

邻接表不唯一
若无向图中有 n 个顶点、e 条边,则其邻接表需n 个头结点和 2e 个表结点。适宜存储稀疏图
无向图中顶点 vi 的度为第 i 个单链表中的结点数
在这里插入图片描述
邻接表特点:

顶点 vi 的出度为第 i 个单链表中的结点个数
顶点 vi 的入度为整个单链表中邻接点域值为 i-1 的结点个数
逆邻接表特点:

顶点 vi 的入度为第 i 个单链表中的结点个数
顶点 vi 的出度为整个单链表中邻接点域值为 i-1 的结点的个数

无向图实现

#include<iostream>
using namespace std;
#define MAX 25

typedef char Vertype;
typedef int Edgetype;
typedef int Status;

typedef struct EdgeNode//边表结点  存放每个顶点的邻接点
{
	int adjvex;//边表下标
	Edgetype weight;//边表权重  若边不存在时即无NULL
	struct EdgeNode *next;//指向下一个邻接点
}EdgeNode;

typedef struct VerNode//顶点表   存放顶点
{
	Vertype data;//顶点元素
	EdgeNode *firstedge;
}VerNode, AdjList[MAX];//邻接表的 顶点元素 和指向邻点的指针

typedef struct
{
	AdjList adjList;//邻接表
	int numVer,numEdge;//顶点数目和边的数目
}GraphAdjList;

Status CreatGraph(GraphAdjList &G)
{
	int i, j, k;
	Edgetype w;
	EdgeNode *e;
	cout << "Enter the number of vertices :"<< endl;
	cin >> G.numVer;
	cout << "Enter the number of Edges :" << endl;
	cin >> G.numEdge;

	cout << "Input vertex content :" << endl;
	for (i = 0; i < G.numVer; i++)
	{
		cin >> G.adjList[i].data;//输入顶点元素
		G.adjList[i].firstedge = NULL;//初始化邻边表为NULL;
	}

	for (k = 0; k < G.numEdge; k++)
	{
		cout <<"Enter the vertex number of the edge (Vi, Vj)" << endl;
		cin >> i;
		cin >> j;

		cout << "Enter the weight of edge" << i << "-" << j << endl;
		cin >> w;
		e = new EdgeNode;//将两个顶点相结即可。
		e->adjvex = j;// 邻接序号为j
		e->next = G.adjList[i].firstedge;//i的第一个邻接指针 为e的指针
		e->weight = w;
		G.adjList[i].firstedge = e;


		//有向图则只有生成一次即可
		e = new EdgeNode;
		e->adjvex = i;//无向图 重复一遍
		e->next = G.adjList[j].firstedge;
		G.adjList[j].firstedge = e;
		e->weight = w;
	}
	return 0;
}

//输出无向图
Status DispGraph(GraphAdjList &G)
{
	int i, j, k;
	cout <<"Output element of ver" << endl;
	for (i = 0; i < G.numVer; i++)
	{
		cout << G.adjList[i].data << '\t';
	}

	cout << "Output weight"<< endl;
	for (k = 0; k < G.numVer; k++)
	{
		EdgeNode *p = G.adjList[k].firstedge;//中间指针
		cout <<"xaibiao"<< k <<"constent"<< G.adjList[k].data << "jiedian:" << endl;
		while (p != NULL)
		{
			cout <<G.adjList[k].data<< "->" << p->adjvex << '\t' << p->weight << '\t' << endl;
			p = p->next;
		}
	}
	/*
	for (k = 0; k < G.numEdge; k++)
	{
		//cout << G.adjList[k].firstedge->adjvex << '\t' << G.adjList[k].firstedge->weight << '\t'<<G.adjList[k].firstedge->next->adjvex<<endl;
		cout << G.adjList[k].firstedge->weight << '\t';
	}
	*/
	return 0;
}
//返回一个顶点的位置 和其邻接表内容
Status OutGraph_x(GraphAdjList &G)
{
	cout <<"请输入需要找的顶点内容: " << endl;
	Vertype x;
	cin >> x;
	for (int i = 0; i < G.numVer; i++)
	{
		if(G.adjList[i].data == x)
		{
			cout << "该元素在图中的位置为: " <<i<<"。  相关邻接表为"<<endl;
			EdgeNode *p = G.adjList[i].firstedge;
			while (p != NULL)
			{
				cout << p->adjvex << '\t' << p->weight << '\t' << endl;
				p = p->next;
			}
		}
	}
	return 0;
}
//新增一个顶点和对应边
Status AddGraph_x(GraphAdjList &G)
{
	Vertype x;
	Edgetype edg_num;
	int w;
	int i;
	EdgeNode *p;
	if (G.numVer >= MAX)
	{
		cout << "Graph memory is full and cannot be expanded "<< endl;
		return NULL;
	}
	else
	{
		cout << "请输入需要插入的新顶点内容: " << endl;
		cin >> x;
		G.numVer++;
		G.adjList[G.numVer - 1].data = x;//顶点内容赋值
		G.adjList[G.numVer - 1].firstedge = NULL;//顶点指针NULL初始化

		cout << "Please enter the number of new edges" << endl;//新增边的数目
		//如果不成边呢
		cin >> edg_num;
		G.numEdge = G.numEdge+ edg_num;
		p = new EdgeNode;
		for (int j = 0; j < edg_num; j++)
		{
			cout << "请输入与其成边的顶点位置" << endl;
			cin >> i;
			cout << "请输入权重" << endl;
			cin >> w;

			/*while (p != NULL)
			{
			p = p->next;//找到最后一个结点为空时
			}*/
			//p = new EdgeNode;
			p->adjvex = G.numVer - 1;
			p->next = G.adjList[i].firstedge;
			G.adjList[i].firstedge = p;
			p->weight = w;

			//p = new EdgeNode;
			p->adjvex = i;
			p->next = G.adjList[G.numVer - 1].firstedge;
			G.adjList[G.numVer - 1].firstedge = p;
			p->weight = w;
		}
	}

	return 0;
}
//删除一个顶点  
Status DelGraph_x(GraphAdjList &G)
{
	Vertype x;
	cout <<"请输入需要删除的顶点:" << endl;
	cin >> x;
	for (int i = 0; i < G.numVer; i++)
	{
		if (G.adjList[i].data == x)
		{
			G.adjList[i].data = NULL;//因为是数组类型 其结构必定存在 所以将其置为空
			//free((void *)G.adjList[i].data); //释放顶点
			G.adjList[i].firstedge=NULL;
		}
	}
	return 0;
}
int main()
{
	GraphAdjList G;
	CreatGraph(G);
	DispGraph(G);
	OutGraph_x(G);
	AddGraph_x(G);
	DispGraph(G);
	DelGraph_x(G);
	DispGraph(G);
	return 0;
}

在这里插入图片描述

有向图的实现

#include<iostream>
using namespace std;
#define MAX 25

typedef char Vertype;
typedef int Edgetype;
typedef int Status;

typedef struct EdgeNode//边表结点  存放每个顶点的邻接点
{
	int adjvex;//边表下标
	Edgetype weight;//边表权重  若边不存在时即无NULL
	struct EdgeNode *next;//指向下一个邻接点
}EdgeNode;

typedef struct VerNode//顶点表   存放顶点
{
	Vertype data;//顶点元素
	EdgeNode *firstedge;
}VerNode, AdjList[MAX];//邻接表的 顶点元素 和指向邻点的指针

typedef struct
{
	AdjList adjList;//邻接表
	int numVer, numEdge;//顶点数目和边的数目
}GraphAdjList;

Status CreatGraph(GraphAdjList &G)
{
	int i, j, k;
	Edgetype w;
	EdgeNode *e;
	cout << "Enter the number of vertices :" << endl;
	cin >> G.numVer;
	cout << "Enter the number of Edges :" << endl;
	cin >> G.numEdge;

	cout << "Input vertex content :" << endl;
	for (i = 0; i < G.numVer; i++)
	{
		cin >> G.adjList[i].data;//输入顶点元素
		G.adjList[i].firstedge = NULL;//初始化邻边表为NULL;
	}

	for (k = 0; k < G.numEdge; k++)
	{
		cout << "Enter the vertex number of the edge (Vi->Vj)" << endl;
		cin >> i;
		cin >> j;

		cout << "Enter the weight of edge" << i << "-" << j << endl;
		cin >> w;
		e = new EdgeNode;//将两个顶点相结即可。
		e->adjvex = j;// 邻接序号为j
		e->next = G.adjList[i].firstedge;//i的第一个邻接指针 为e的指针
		e->weight = w;
		G.adjList[i].firstedge = e;


		//有向图则只有生成一次即可
		/*
		e = new EdgeNode;
		e->adjvex = i;//无向图 重复一遍
		e->next = G.adjList[j].firstedge;
		G.adjList[j].firstedge = e;
		e->weight = w;*/
	}
	return 0;
}

Status DispGraph(GraphAdjList &G)
{
	int i, j, k;
	cout << "Output element of ver" << endl;
	for (i = 0; i < G.numVer; i++)
	{
		cout << G.adjList[i].data << '\t';
	}

	cout << "Output weight" << endl;
	for (k = 0; k < G.numVer; k++)
	{
		EdgeNode *p = G.adjList[k].firstedge;//中间指针
		cout << "xaibiao" << k << "constent" << G.adjList[k].data << "jiedian:" << endl;
		while (p != NULL)
		{
			cout << G.adjList[k].data << "->" << p->adjvex << '\t' << p->weight << '\t' << endl;
			p = p->next;
		}
	}



	return 0;
}
int main()
{
	GraphAdjList G;
	CreatGraph(G);
	DispGraph(G);
	return 0;
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、结构(有向、无向等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
数据结构是指组织和存储数据的方式,而是一种重要的数据结构之一。有向是一种,其中每条边都有一个方向,表示顶点之间的一种单向关系。有向的逻辑结构可以用有向邻接表来表示。[1] 无向是另一种,其中顶点之间的关系是双向的,即没有明确的方向性。在无向中,任意两个顶点之间都存在边。无向完全是指在无向中,任意两个顶点之间都有边相连。对于含有n个顶点的无向完全,它有n*(n-1)/2条边。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [数据结构——有向和无向的创建与遍历](https://blog.csdn.net/zswsx123/article/details/115394789)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [(数据结构——、顶点、无向边、无向、有向边、有向、简单、无向完全、有向完全、稀疏、...](https://blog.csdn.net/qq_40888863/article/details/120160997)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值