图的存储方式——邻接矩阵与邻接表

新人第一次发,可能有错,请大佬们多多包涵

一、邻接矩阵(Adjacency Matrix)

1.基本介绍

言简意赅,邻接矩阵时就是表示顶点间相邻关系的矩阵!

我认为,邻接矩阵可以分为三种:

1.无向无权邻接矩阵   A[i][j]=    1(若i,j相邻)并且A[j][i]=1   or    0(不相邻)

2.有向无权邻接矩阵    A[i][j]=    1(若i,j相邻)   or    0(不相邻)

3.有向有权邻接矩阵。 A[i][j]=    权值(若i,j相邻)   or    0(不相邻)

2.代码解释——注意在这里我们构建的是无向无边邻接矩阵

1.邻接矩阵类型的结构体建立

在这里,我们定义了 ADJ_MATRIX

1.邻接矩阵的 顶点数量(vexnum),边(弧)的数量(arcnum)。

2.顶点的内容——构建了一个内容数组(vexs[ ])。

3.展现弧关系的矩阵——构建了一个弧关系二维数组arcs[ ][ ]。

const int MAXLEN=100;
typedef char VEXTYPE;
typedef int ARCTYPE;

//构建邻接矩阵
struct ADJ_MATRIX
{
	int vexnum,arcnum;				//点数和弧数
	VEXTYPE vexs[MAXLEN];			//顶点内容 的数组(这里是字符型)
	ARCTYPE arcs[MAXLEN][MAXLEN];	//表示弧关系的矩阵
};

2.定义构造邻接矩阵 的函数

第一步:为表示邻接矩阵类型的结构体分配空间。

第二步:输入顶点数(vexnum)和弧数(arcnum)。

第三步:给顶点数组赋值(顶点的内容是什么),注意这里是字符型的。

第四步:初始化弧关系二维数组,让他们的值都为零。

第五步:输入边(i,j)——确定顶点之间的关系。

//直接创建邻接矩阵
ADJ_MATRIX* Create_Matrix()
{
	ADJ_MATRIX* matrix_graph;
	
	//1.分配空间
	matrix_graph = new ADJ_MATRIX;
	
	//2.输入顶点数vexnum,弧数arcnum
	cin>>matrix_graph->vexnum>>matrix_graph->arcnum;
	
	//!!!!!3.为顶点内容(vexs[i])赋值
	for(int i=0;i<matrix_graph->vexnum;i++)
		cin>>matrix_graph->vexs[i];//char
	/*
	vexs[i]   a b c d e
	下标      0 1 2 3 4
	*/
	
	//4.初始化邻接矩阵
	for(int i=0;i<matrix_graph->vexnum;i++)
		for(int j=0;j<matrix_graph->vexnum;j++)
			matrix_graph->arcs[i][j]=0;
	
	//5.输入弧——确定顶点之间的关系
	for(int i=0;i<matrix_graph->arcnum;i++)
	{
		int x,y;
		cin>>x>>y;//输入有联系顶点的下标
		matrix_graph->arcs[x][y]=1;
		matrix_graph->arcs[y][x]=1;
	}
	
	return matrix_graph;
}

3.邻接矩阵的输出——不多说,直接上代码

//输出邻接矩阵
void Print_ADJ_Matrix(ADJ_MATRIX* matrix_graph)
{
	//在最上方展示顶点内容
	cout<<"  ";
	for(int i=0;i<matrix_graph->vexnum;i++)
		cout<<char(matrix_graph->vexs[i])<<" ";
	cout<<endl;
	
	for(int i=0;i<matrix_graph->vexnum;i++)
	{
		cout<<matrix_graph->vexs[i]<<" ";//在最左侧展示顶点内容
		for(int j=0;j<matrix_graph->vexnum;j++)
			cout<<matrix_graph->arcs[i][j]<<" ";
		cout<<endl;
	}
}

 4.(展示)main函数运行与运行案例

int main()
{						
	ADJ_MATRIX* M_g;		//定义一个ADJ_MATRIX的指针对象——M_g
	
	M_g=Create_Matrix();	//2.创建
	
	Print_ADJ_Matrix(M_g);	//3.打印
	
	return 0;				//注意习惯
}

**********************************************运行——输入*************************************************

5 5
a b c d e
0 1
1 2
2 3   
3 4
1 4 

**********************************************运行——输出*************************************************



二、邻接表  (Adjacency List) 

1.基本介绍

一种链式存储方法,对于图中每个顶点vi建立一个单链表,将与vi相连的顶点放在这个链表中。二每一个单链表有边节点和表头结点组成。

表头结点
vex_datafirstarc
边结点
vex_datainfonextarc

2.代码解释——在这里我们构建的是无向无权邻接表

1.邻接矩阵类型(无向图)的结构体建立

我们定义了 ADJ_LIST

1.邻接表的 顶点数量(vexnum),边(弧)的数量(arcnum)。

2.邻接表 adjlist[ ]     (每个顶点相连关系的链表)

        (1) VEXNODE

                [1] vex_data——数据域

                [2] firstarc——链域

        (2)  ARCNODE

                [1] vex_data——临界点域

                [2] info——数据域 在这里,我们默认为0。

                [3] nextarc——链域

const int MAXLEN=100;
typedef char VEXTYPE; 
typedef int ARCTYPE;

//邻(lin)接表的边结点
struct ARCNODE
{
	VEXTYPE vex_data;					//顶点的值
	int info;							//与边相关的信息,如权值
	ARCNODE* nextarc;					
};

//邻接表的表头结点
struct VEXNODE
{
	VEXTYPE vex_data;
	ARCNODE* firstarc;
};

//构建邻接表
struct ADJ_LIST
{
	int vexnum,arcnum;
	VEXNODE adjlist[MAXLEN];		//每个点的邻接链表构成的数组adjlist
}

2.定义构造邻接表 的函数

第一步:为表示邻接表类型的结构体分配空间。

第二步:输入顶点数(vexnum)和弧数(arcnum)。

第三步:给顶点数组赋值(顶点的内容是什么),注意这里是字符型的。

第四步:输入边(i,j)——确定顶点之间的关系。由于这里是无向图,所有要操作两次

ADJ_LIST* Create_List()
{
	ADJ_LIST* list_graph;
	ARCNODE* p;
	
	//1.list_graph开辟空间
	list_graph=new ADJ_LIST;
	
	//2.输入点数,边数
	cin>>list_graph->vexnum>>list_graph->arcnum;
	
	//3.为顶点内容赋值(adjlist[i].vex_data)并进行初始化
	for(int i=0;i<list_graph->vexnum;i++)
	{
		cin>>list_graph->adjlist[i].vex_data;
		list_graph->adjlist[i].firstarc=NULL;
	}
	//4.根据边的关系建表
	for(int i=0;i<list_graph->arcnum;i++)
	{
		int x,y;
		cin>>x>>y;
		
		//(1)在下标x的链表上插入y的内容
		p=new ARCNODE;
		p->vex_data=list_graph->adjlist[y].vex_data;
		p->nextarc=list_graph->adjlist[x].firstarc;
		list_graph->adjlist[x].firstarc=p;
		
		//(2)在下标y的链表上插入x的内容
		p=new ARCNODE;
		p->vex_data=list_graph->adjlist[x].vex_data;
		p->nextarc=list_graph->adjlist[y].firstarc;
		list_graph->adjlist[y].firstarc=p;
	}
	return list_graph;
}

3.邻接表的输出——不多说,直接上代码

void Print_ADJ_List(ADJ_LIST *list_graph)
{
	ARCNODE* p;
	for(int i=0;i<list_graph->vexnum;i++)
	{
		cout<<"<"<<i<<"> "<<list_graph->adjlist[i].vex_data;
		p=list_graph->adjlist[i].firstarc;
		while(p)
		{
			cout<<"->"<<p->vex_data;
			p=p->nextarc;
		}
		cout<<"->^"<<endl;
	}
}

4.(展示)main函数运行与运行案例

int main()
{
	ADJ_LIST* L_graph;			//定义ADJ_LIST
	
	L_graph=Create_List();		//创建
	
	Print_ADJ_List(L_graph);	//输出
	return 0;
}

**********************************************运行——输入*************************************************

5 5
a b c d e
0 1
1 2
2 3   
3 4
1 4 

**********************************************运行——输出*************************************************

细心的同学应该观察到这就是有上面矩阵的案例转变而来的

3.邻接矩阵转邻接表

//邻接矩阵转邻接表
ADJ_LIST* Matrix_To_List(ADJ_MATRIX* matrix_graph) {
	ADJ_LIST* list_graph;
	ARCNODE *p;

	//1.分配空间
	list_graph = new ADJ_LIST;

	//2.给邻接表赋顶点数vexnum,弧数arcnum
	list_graph->vexnum = matrix_graph->vexnum;
	list_graph->arcnum = matrix_graph->arcnum;

	//3.构建邻接表(邻接链表的数组)
	for (int i = 0; i < list_graph->vexnum; i++) {
		//初始化顶点i的一支单链表
		list_graph->adjlist[i].vex_data = matrix_graph->vexs[i];
		list_graph->adjlist[i].firstarc = NULL;

		//对于除了i的顶点进行遍历.
		for (int j = 0; j < list_graph->vexnum; j++) {
			//注意:是头插法!!!
			if (matrix_graph->arcs[i][j]) {	//若有i和j联系(matrix_graph[i][j])则插入j
				p = new ARCNODE;
				p->vex_data = matrix_graph->vexs[j];
				p->nextarc = list_graph->adjlist[i].firstarc;
				list_graph->adjlist[i].firstarc = p;
			}
		}
	}
	return list_graph;
}

(展示)main函数运行与运行案例

int main() {
	ADJ_MATRIX* M_g;
	ADJ_LIST* L_g;

	M_g =Create_Matrix();
	Print_ADJ_Matrix(M_g);

	L_g=Matrix_To_List(M_g);
	Print_ADJ_List(L_g);
	return 0;
}

**********************************************运行——输入*************************************************

5 5
a b c d e
0 1
1 2
2 3   
3 4
1 4 

**********************************************运行——输出*************************************************

三.最后给大家一个最终的源代码内容,可以在电脑上试着自己运行

#include<iostream>
using namespace std;

const int MAXLEN = 100;
typedef char VEXTYPE;
typedef int ARCTYPE;

//构建邻接矩阵
struct ADJ_MATRIX {
	int vexnum, arcnum;				//点数和弧数
	VEXTYPE vexs[MAXLEN];			//顶点内容 的数组(这里是字符型)
	ARCTYPE arcs[MAXLEN][MAXLEN];	//表示弧关系的矩阵
};

//邻(lin)接表的边结点
struct ARCNODE {
	VEXTYPE vex_data;					//顶点的值
	int info = 0;							//与边相关的信息,如权值
	ARCNODE* nextarc;
};

//邻接表的表头结点
struct VEXNODE {
	VEXTYPE vex_data;
	ARCNODE* firstarc;
};

//构建邻接表
struct ADJ_LIST {
	int vexnum, arcnum;
	VEXNODE adjlist[MAXLEN];		//每个点的邻接链表构成的数组adjlist
};

//直接创建邻接矩阵
ADJ_MATRIX* Create_Matrix() {
	ADJ_MATRIX* matrix_graph;

	//1.分配空间
	matrix_graph = new ADJ_MATRIX;

	//2.输入顶点数vexnum,弧数arcnum
	cin >> matrix_graph->vexnum >> matrix_graph->arcnum;

	//!!!!!3.为顶点内容(vexs[i])赋值
	for (int i = 0; i < matrix_graph->vexnum; i++)
		cin >> matrix_graph->vexs[i]; //char
	/*
	vexs[i]   a b c d e
	下标      0 1 2 3 4
	*/

	//4.初始化邻接矩阵
	for (int i = 0; i < matrix_graph->vexnum; i++)
		for (int j = 0; j < matrix_graph->vexnum; j++)
			matrix_graph->arcs[i][j] = 0;

	//5.输入弧——确定顶点之间的关系
	for (int i = 0; i < matrix_graph->arcnum; i++) {
		int x, y;
		cin >> x >> y; //输入有联系顶点的下标
		matrix_graph->arcs[x][y] = 1;
		matrix_graph->arcs[y][x] = 1;
	}

	return matrix_graph;
}

//直接创建邻接表
ADJ_LIST* Create_List() {
	ADJ_LIST* list_graph;
	ARCNODE* p;

	//1.list_graph开辟空间
	list_graph = new ADJ_LIST;

	//2.输入点数,边数
	cin >> list_graph->vexnum >> list_graph->arcnum;

	//3.为顶点内容赋值(adjlist[i].vex_data)并进行初始化
	for (int i = 0; i < list_graph->vexnum; i++) {
		cin >> list_graph->adjlist[i].vex_data;
		list_graph->adjlist[i].firstarc = NULL;
	}
	//4.根据边的关系建表
	for (int i = 0; i < list_graph->arcnum; i++) {
		int x, y;
		cin >> x >> y;

		//(1)在下标x的链表上插入y的内容
		p = new ARCNODE;
		p->vex_data = list_graph->adjlist[y].vex_data;
		p->nextarc = list_graph->adjlist[x].firstarc;
		list_graph->adjlist[x].firstarc = p;

		//(2)在下标y的链表上插入x的内容
		p = new ARCNODE;
		p->vex_data = list_graph->adjlist[x].vex_data;
		p->nextarc = list_graph->adjlist[y].firstarc;
		list_graph->adjlist[y].firstarc = p;
	}
	return list_graph;
}

//输出邻接矩阵
void Print_ADJ_Matrix(ADJ_MATRIX* matrix_graph)
{
	//在最上方展示顶点内容
	cout<<"  ";
	for(int i=0;i<matrix_graph->vexnum;i++)
		cout<<char(matrix_graph->vexs[i])<<" ";
	cout<<endl;
	
	for(int i=0;i<matrix_graph->vexnum;i++)
	{
		cout<<char(matrix_graph->vexs[i])<<" ";//在最左侧展示顶点内容
		for(int j=0;j<matrix_graph->vexnum;j++)
			cout<<matrix_graph->arcs[i][j]<<" ";
		cout<<endl;
	}
}

//输出邻接表
void Print_ADJ_List(ADJ_LIST *list_graph) {
	ARCNODE* p;
	for (int i = 0; i < list_graph->vexnum; i++) {
		cout << "<" << i << "> " << list_graph->adjlist[i].vex_data;
		p = list_graph->adjlist[i].firstarc;
		while (p) {
			cout << "->" << p->vex_data;
			p = p->nextarc;
		}
		cout << "->^" << endl;
	}
}

//邻接矩阵转邻接表
ADJ_LIST* Matrix_To_List(ADJ_MATRIX* matrix_graph) {
	ADJ_LIST* list_graph;
	ARCNODE *p;

	//1.分配空间
	list_graph = new ADJ_LIST;

	//2.给邻接表赋顶点数vexnum,弧数arcnum
	list_graph->vexnum = matrix_graph->vexnum;
	list_graph->arcnum = matrix_graph->arcnum;

	//3.构建邻接表(邻接链表的数组)
	for (int i = 0; i < list_graph->vexnum; i++) {
		//初始化顶点i的一支单链表
		list_graph->adjlist[i].vex_data = matrix_graph->vexs[i];
		list_graph->adjlist[i].firstarc = NULL;

		//对于除了i的顶点进行遍历.
		for (int j = 0; j < list_graph->vexnum; j++) {
			//注意:是头插法!!!
			if (matrix_graph->arcs[i][j]) {	//若有i和j联系(matrix_graph[i][j])则插入j
				p = new ARCNODE;
				p->vex_data = matrix_graph->vexs[j];
				p->nextarc = list_graph->adjlist[i].firstarc;
				list_graph->adjlist[i].firstarc = p;
			}
		}
	}
	return list_graph;
}

  • 47
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小 range

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

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

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

打赏作者

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

抵扣说明:

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

余额充值