图的三种存储结构:邻接矩阵表示法+链表法+十字链表法

一、邻接矩阵表示法

1、简介

图的邻接矩阵表示法也称作数组表示法

它采用两个数组来表示图:一个是用于存储顶点信息的一维数组,另一个是用于存储图中顶点之间关联关系的二维数组,称为邻接矩阵。

2、示例

(1) 无向图邻接矩阵

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第1张图片

(2)有向图邻接矩阵 

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第2张图片

(3)有向图网络的邻接矩阵 

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第3张图片

其中对角线值为0,若两点之间有弧存在即在对应的矩阵位置写权值,若没有边存在即是∞。

3、存储有向网

(1)要存储的有向网

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第4张图片

(2)C语言代码 

#include
#define MAX_VERTEM_NUM 10 
#define INFINITY 32768

typedef enum{
	DG,DN,UDG,UDN	
}graghKind;
//digraph  DG有向图
//directed network  DN有向网
//undirected graph  UDG无向图
//undirected network  UDN无向网

typedef int vertemData;

typedef struct {
	vertemData vert[MAX_VERTEM_NUM];			//顶点向量
	int adj[MAX_VERTEM_NUM][MAX_VERTEM_NUM];	//邻接矩阵
	int vertNum,arcNum;							//图的顶点数和弧数
	graghKind gragh;							//图的类型
}adjMatrix;

//求顶点位置
int locateVertem(adjMatrix *G,vertemData v){
	for(int j=0;jvertNum;j++)
	{
		if(G->vert[j]==v)
		{
			return j;
		}
	}
}

//创建有向网
int creatDN(adjMatrix *G){
	int i,j,k,weight;
	vertemData v1,v2;
	printf("请输入图的顶点数和弧数:\n");
	scanf("%d %d",&G->vertNum,&G->arcNum);
	for(i=0;ivertNum;i++)
		for(j=0;jvertNum;j++)
			G->adj[i][j] = INFINITY;	
	for(i=0;ivertNum;i++)
	{
		printf("请输入图的顶点%d:\n",i);
		scanf("%d",&G->vert[i]);
	}
	for(k=0;karcNum;k++){
		printf("请输入弧%d的两个顶点和权值:\n",k);
		scanf("%d %d %d",&v1,&v2,&weight);
		i = locateVertem(G,v1);
		j = locateVertem(G,v2);
		G->adj[i][j] = weight;
	}
	printf("\n有向网存储完毕!");	
	return 0;
}

int main(){
	adjMatrix G;
	creatDN(&G);
	return 0;
}

(3)运行结果 

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第5张图片

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第6张图片

(4)时间复杂度

该算法的时间复杂度为O(n^2+t×n),其中O(n^2时间耗费在对二维数组每个分量的初始化赋值上。O(t×n)的时间耗费在有向网中边权的赋值上。

3、特点

  • 存储空间。对于无向图而言,它的邻接矩阵是对称矩阵,因此我们可以采用特殊矩阵的压缩存储法,即只存储其下三角即可,这样一个具有n个顶点的无向图G,它的邻接矩阵需要n(n-1)/2个存储空间即可。但对于有向图而言,其中的弧是有方向的,,因此,有向图的邻接矩阵不一定是对称矩阵,对于有向图的邻接矩阵的存储则需要n^2个存储空间。
  • 便于运算。采用邻接矩阵表示法,便于判定图中任意两个顶点之间是否有边相连,即根据A[i,j]=0或1来判断。另外,还便于求得各个顶点的度。对于无向图而言,其邻接矩阵第i行元素之和就是图中第i个顶点的度。
  • 不适用于稀疏图。 边很少的稀疏图用邻接矩阵方法会造成存储空间的极大浪费。

 二、邻接表

1、简介

图的邻接表存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。邻接表由表头结点表结点两部分组成。

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第7张图片

2、示例

(1)无向图及其邻接表

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第8张图片

 (2)有向图邻接表和逆邻接表

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第9张图片

(3)带权图邻接表

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第10张图片

 3、存储带权图邻接表

(1)要存储的带权无向图

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第11张图片

(2)C语言代码

#include
#include
#define MAX_VERTEM_NUM 10 
#define INFINITY 32768

typedef enum{
	DG,DN,UDG,UDN	
}graghKind;
//digraph  DG有向图
//directed network  DN有向网
//undirected graph  UDG无向图
//undirected network  UDN无向网

typedef int vertemData;

//表结点
typedef struct arcNode{
	int adjvex;
	int weight;
	struct arcNode *next;
}arcNode;

//表头节点
typedef struct{
	vertemData data;
	arcNode *arc;
}headNode;

//邻接表
typedef struct{
	headNode vertem[MAX_VERTEM_NUM];
	int vertNum,arcNun;
	graghKind gragh;
}arcList;

//表头结点插入新的表节点
void insert(headNode *h,vertemData v,int weight)
{
	arcNode *t,*m;
	t = (arcNode*)malloc(sizeof(arcNode));
	t->next = NULL;
	t->adjvex = v;
	t->weight = weight;
	if(h->arc==NULL) h->arc = t;
	else{
		m = h->arc;
		while(1)
		{
			if(m->next==NULL) 
			{
				m->next = t;
				break;
			}
			else{
				m = m->next;
			} 
		}
	}
	free(t);
}

//初始化邻接表
void init_arcList(arcList *L,int vn)
{
	for(int i=0;ivertem[i].arc = NULL;
	}
}

//存储无向网
void create_weight_UDN(arcList *L)
{
	int i,j,n,vert,weight;
	printf("请输入图的顶点数和弧数:\n");
	scanf("%d %d",&L->vertNum,&L->arcNun);
	init_arcList(L,L->vertNum);
	for(i=0;ivertNum;i++)
	{
		printf("请输入顶点%d的弧数:\n",i);
		scanf("%d",&n);
		for(j=0;jvertem[i],vert,weight);
		}
	}
	printf("\n使用邻接表存储无向网完毕!");
}

int main()
{
	arcList *L;
	L = (arcList*)malloc(sizeof(arcList));
	create_weight_UDN(L);
	return 0;
}

(3)运行结果

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第12张图片

4、特点 

  • 适用稀疏图。对于有n个顶点、e条边的无向图而言,若采取邻接表作为存储结构,则需要n个表头结点和2e个表结点。很显然在边很稀疏(即e远小于n(n-1)/2时)的情况下,用邻接表存储所需的空间要比邻接矩阵所需的n(n-1)/2要节省得多。
  • 求顶点的入度并不方便,它需要扫描整个邻接表才能得到结果。
  • 判定任意两个顶点之间是否有边或弧相连不及邻接矩阵法方便。

三、十字链表法

1、简介

将有向图的邻接表和逆邻接表结合在一起,就得到了有向图的另一种链式存储结构——十字链表。

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第13张图片

2、示例

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第14张图片

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第15张图片

3、存储有向网

(1)要存储的有向网

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第16张图片

(2)C语言代码 

#include
#include
#define MAX_VERTEM_NUM 10 
#define INFINITY 32768

typedef enum{
	DG,DN,UDG,UDN	
}graghKind;
//digraph  DG有向图
//directed network  DN有向网
//undirected graph  UDG无向图
//undirected network  UDN无向网

typedef int vertemData;

//表结点
typedef struct arcNode{
	int tailvex;
	int headvex;
	vertemData arcinfo;
	struct arcNode *tnext;
	struct arcNode *hnext;
}arcNode;

//表头节点
typedef struct{
	vertemData vexinfo;
	arcNode *firstin;
	arcNode *firstout;
}headNode;

//十字邻接表
typedef struct{
	headNode vertem[MAX_VERTEM_NUM];
	int vertNum,arcNun;
	graghKind gragh;
}arcList;

//查询顶点位置
int locate_vertem(arcList *L,vertemData v)
{
	for(int i=0;ivertNum;i++)
	{
		if(L->vertem[i].vexinfo==v) return i;
	}
	return 0;
}

//创建十字链表
void create_arcList(arcList *L)
{
	int i,j,k,head,tail,info;
	printf("请输入图的顶点数和弧的数量:\n");
	scanf("%d %d",&L->vertNum,&L->arcNun);
	for(i=0;ivertNum;i++)
	{
		printf("请输入第%d个顶点的值:\n",i);
		scanf("%d",&L->vertem[i].vexinfo);
		L->vertem[i].firstin = L->vertem[i].firstout = NULL;
	}
	for(i=0;iarcNun;i++)
	{
		printf("请输入弧%d的信息:\n",i+1);
		scanf("%d %d %d",&tail,&head,&info);
		arcNode *t = (arcNode*)malloc(sizeof(arcNode));
		t->tailvex = tail;
		t->headvex = head;
		t->arcinfo = info;
		t->hnext = t->tnext = NULL;
		j = locate_vertem(L,tail);
		k = locate_vertem(L,head);
		if(L->vertem[j].firstout==NULL) L->vertem[j].firstout = t;
		else{
			arcNode *m = L->vertem[j].firstout;
			while(1)
			{
				if(m->tnext==NULL) 
				{
					m->tnext = t;
					break;
				}
				else m = m->tnext;
			}
		}
		if(L->vertem[k].firstin==NULL) L->vertem[j].firstin = t->hnext;
		else{
			arcNode *m = L->vertem[k].firstin;
			while(1)
			{
				if(m->hnext==NULL) 
				{
					m->hnext = t->hnext;
					break;
				}
				else m = m->hnext;
			}
		}
		free(t);
	}
	printf("使用十字链表法创建有向网完毕!");
}

int main()
{
	arcList *L = (arcList*)malloc(sizeof(arcList));
	create_arcList(L);
	return 0;
}

(3)运行结果 

图的三种存储结构:邻接矩阵表示法+链表法+十字链表法_第17张图片

 4、特点

  • 容易求得顶点的出度和入度

你可能感兴趣的:(数据结构与算法,链表,数据结构,算法)