数据结构-图的4种结构-邻接矩阵-邻接表-十字链表-邻接多重链表

在这里插入图片描述
边节点数据结构:iver,ilink,jver,jlink
创建边节点时,查找iver,jver对应下标开始最后ilink,jlink为空时,把ilink或jlink指向当前所创建的节点。
顶点的edgefrist指针为空时表示创建的边节点为该顶点的第一条边。edgefirst直接指向该节点。

structfun.h

//数据结构函数头文件

#include <stdio.h>
#include <iostream>
#include<string>

using std::cout;
using std::cin;
using std::string;

#define MAXSIZE 100
#define OK 1
#define ERROR 0
#define INFINITY 65535//无穷大
typedef string ElemType;
typedef string VertexType;//图顶点数据类型
typedef int EdgeType;//图边的数据类型

//数据结构-图-----------------------------------------------------------------------------

//1、邻接矩阵(Adjacency Martix)
	//设置一个顶点数组vertex[],设置一个边数组arc[][]
typedef struct
{
	//图顶点数组
	VertexType vertex[MAXSIZE];
	//图边数组
	EdgeType arc[MAXSIZE][MAXSIZE];	
	int vertexnum,arcnum;
}AdjMarGraph;

//2、邻接表(Adjacency List)
	//设置一个顶点数组vertex[],设置一个边的链表,顶点的next指向所对应的链表

typedef struct EdgeNode//边链表节点
{
	EdgeType arcVertex;
	int weight;//权值
	EdgeNode *next;
}EdgeNode;

typedef struct//顶点数组
{
	VertexType vertex;
	EdgeNode *firstEdge;
}VertexList[MAXSIZE];

typedef struct//图结构
{
	VertexList vlist;
	int numVertex,numArc;

}AdjListGraph;

//3、十字链表(Orthogonal->正交的 List)
	//设置一个顶点数组vertex[],设置一个边的链表,顶点的next指向所对应的链表

//链表节点 tailvex headvex headlink,taillink; 改成invex,outvex,outlink,inlink更好理解
                                                //入顶点,出顶点,出链接,入链接
typedef struct OrthogonalLinkNode
{
	EdgeType invex,outvex;
	OrthogonalLinkNode *outlink,*inlink;
	int weight;//边的权重
}OrthogonalLinkNode;

//数组顶点节点 vertex 顶点 edgein 入边 edgeout 出边
typedef struct
{
	VertexType vertex;
	OrthogonalLinkNode *edgein,*edgeout;
}OrthogonalEdgeNode[MAXSIZE];

//十字链表结构
typedef struct 
{
	OrthogonalEdgeNode vertexlist;
	int numvertex,numedge;
}OrthogonalListGraph;

//4、无向图 邻接多重表结构Adjacency Multiple Table(邻接多重表就是一个顶点的多条边用链表链接)
//ivex ilink jvex jlink (ivex jvex 边的两个顶点,ilink指向值与ivex相同的jvex的节点,jlink指向值与jvex相同的下一个节点。

typedef struct AMTEdgeNode//边链表节点
{
	EdgeType iver,jver;
	int weight;//权值
	AMTEdgeNode *ilink,*jlink;
}AMTEdgeNode;

typedef struct//顶点数组
{
	VertexType vertex;
	AMTEdgeNode *firstEdge;
}AMTVertexList[MAXSIZE];

typedef struct//图结构
{
	AMTVertexList vlist;
	int numVertex,numArc;

}AdjacencyMultipleTableGraph;

//1、邻接矩阵
	//无向图的邻接矩阵
int CreateAdjMaxGraph(AdjMarGraph *amg);

//2、邻接表
int CreateAdjListGraph(AdjListGraph *alg);

//3、十字链表
int CreateOrthogonalListGraph(OrthogonalListGraph *olg);

//4、邻接多重表结构
int CreateAdjacencyMultipleTableGraph(AdjacencyMultipleTableGraph *amtg);

structfun.cpp

#include<iostream>
#include<stdio.h>
#include<string>
#include<sstream>
#include"structfun.h"


using std::cout;
using std::cin;
using std::string;
using std::endl;
using std::ostringstream;

//图结构函数-----------------------------------------------
//1、邻接矩阵
	//图的邻接矩阵
int CreateAdjMaxGraph(AdjMarGraph *amg)
{
	int i=0;
	amg->vertexnum=0;
	amg->arcnum=0;

	while(1)//输入顶点;
	{
		printf("请输入顶点,结束用#号:");
	/*	scanf("%s",&amg->vertex[i]);*///string不能采用scanf,采用scanf必须先给字符串
		//预先分配空间,然后采用amg->vertex[i][0]scanf采用的是字符数组的形式存储字符串。
		//amg->vertex[i].resize(100);
		//scanf("%s",&amg->vertex[i][0]);
		cin>>amg->vertex[i];

		if(amg->vertex[i]=="#")
			break;
		amg->vertexnum++;
		i++;
		
	}
	for(i=0;i<amg->vertexnum;i++)//初始化边值为0
		for(int j=0;j<amg->vertexnum;j++)
		{
			if(i==j)
				amg->arc[i][j]=0;
			else
			amg->arc[i][j]=INFINITY;
		}
	//创建邻接矩阵图的边
	while(1)
	{
		int v1,v2,value;
		printf("请输入图的边的顶点下标(v1,v2,value)结束输入(0,0,0):");
		scanf("%d,%d,%d",&v1,&v2,&value);
		amg->arc[v1][v2]=value;
		/*amg->arc[v2][v1]=value;*///无向图增加对等矩阵另外一边的值
		if(!v1&!v2&!value)
			break;
		amg->arcnum++;	
	}
	
	//输出图的邻接矩阵
	printf("图的邻接矩阵:\n");
	for(i=0;i<amg->vertexnum;i++)
	{
		printf("%s: ",amg->vertex[i].c_str());
		for(int j=0;j<amg->vertexnum;j++)
			{
				printf("%d  ",amg->arc[i][j]);
				if(j==amg->vertexnum-1)
					printf("\n");
			}
	}
return OK;
}

//2、邻接表
int CreateAdjListGraph(AdjListGraph *alg)
{
	int i=0;
	alg->numVertex=0;
	alg->numArc=0;
	while(1)//创建顶点
	{
		printf("请输入邻接表的顶点结束用#:");
		cin>>alg->vlist[i].vertex;
		if(alg->vlist[i].vertex=="#")
			break;
		alg->vlist[i].firstEdge=NULL;
		i++;
		alg->numVertex++;

	}
		while(1)//创建边链表
	{
		int v1=0,v2=0,w=0;
		EdgeNode *edgenode;
		printf("请输入邻接表的顶点对应的边(v1,v2,w)以(0,0,0)结束:");
		scanf("%d,%d,%d",&v1,&v2,&w);

		if(!v1&&!v2&&!w)//(0,0,0)结束
			break;

		edgenode = new EdgeNode();//创建边节点
		edgenode->arcVertex=v2;
		edgenode->weight=w;
		edgenode->next=NULL;

		if(alg->vlist[v1].firstEdge==NULL)//插入边节点
			alg->vlist[v1].firstEdge=edgenode;
		else
		{
			EdgeNode *temp;
			temp=alg->vlist[v1].firstEdge;

			while(temp->next!=NULL)
				temp=temp->next;
			temp->next=edgenode;
		}
		alg->numArc++;
	}
		return OK;
}

//3、十字链表(就是邻接表与逆邻接表合并)好处是方便同时具有图的出边和入边
int CreateOrthogonalListGraph(OrthogonalListGraph *olg)
{
	int i=0;
	olg->numvertex=0;
	olg->numedge=0;

	while(1)//输入顶点
	{
		printf("请输入图的顶点(以#结束):");
		cin>>olg->vertexlist[i].vertex;
		if(olg->vertexlist[i].vertex=="#")
			break;
		olg->numvertex++;
		olg->vertexlist[i].edgein=NULL;
		olg->vertexlist[i].edgeout=NULL;
		i++;
	}

	while(1)//输入图的边
	{
		OrthogonalLinkNode *edge;
		edge=new OrthogonalLinkNode();
		edge->inlink=NULL;
		edge->outlink=NULL;
		int v1=0,v2=0,w=0;
		printf("请输入图的有向边(v1,v2,w)(0,0,0)结束:");
		scanf("%d,%d,%d",&v1,&v2,&w);
		if(!v1&&!v2&&!w)
			break;

		edge->outvex=v2;
		edge->invex=v1;//这一步是逆矩阵合并的步骤--edge->invex都等于链表的头顶点

		if(olg->vertexlist[v1].edgeout==NULL)
		{
			olg->vertexlist[v1].edgeout=edge;

		}else
		{
			OrthogonalLinkNode *temp;
			temp=new OrthogonalLinkNode(); 
			temp=olg->vertexlist[v1].edgeout;
			while(temp->outlink)
				temp=temp->outlink;
			temp->outlink=edge;
		}

		//最后处理图的入边与邻接表相比多了这个步骤,这个步骤是把逆邻接表串联起来,开头位置是edgein
		if(olg->vertexlist[v2].edgein==NULL)
		olg->vertexlist[v2].edgein=edge;
		else
		{
			OrthogonalLinkNode *temp;
			temp=new OrthogonalLinkNode(); 
			temp=olg->vertexlist[v2].edgein;
			while(temp->inlink)
				temp=temp->inlink;
			temp->inlink=edge;
		}

	}
	return OK;
}

//4、邻接多重表结构
int CreateAdjacencyMultipleTableGraph(AdjacencyMultipleTableGraph *amtg)
{
	int i=0;
	amtg->numVertex=0;
	amtg->numArc=0;

	while(1)//创建顶点
	{
		printf("请输入邻接表的顶点结束用#:");
		cin>>amtg->vlist[i].vertex;
		if(amtg->vlist[i].vertex=="#")
			break;
		amtg->vlist[i].firstEdge=NULL;
		i++;
		amtg->numVertex++;
	}

	while(1)//创建边
	{
		int v1,v2,w;
		AMTEdgeNode *node,*temp;
		node=new AMTEdgeNode();
		printf("请输入的边(v1,v2,w)用(0,0,0)结束:");
		scanf("%d,%d,%d",&v1,&v2,&w);
		if(!v1&&!v2&&!w)//(0,0,0)结束
		break;

		node->iver=v1;
		node->jver=v2;
		node->weight=w;
		node->ilink=NULL;
		node->jlink=NULL;


		if(!amtg->vlist[v1].firstEdge)//列表的firstEdge为空则指向节点
			amtg->vlist[v1].firstEdge=node;
		if(!amtg->vlist[v2].firstEdge)//列表的firstEdge为空则指向节点
			amtg->vlist[v2].firstEdge=node;

		if(amtg->vlist[v1].firstEdge!=node)
		{
			temp=new AMTEdgeNode();//处理v1的ilink和jlink
			temp=amtg->vlist[v1].firstEdge;
			while(temp)
			{
				if(temp->iver==v1)
				{
					if(!temp->ilink)//沿着链表找到ilink的最后为空,此时指针可以指向node
					{
						temp->ilink=node;
						break;
					}
					temp=temp->ilink;//否则继续下一个ilink节点
				}
				else 
				{
					if(!temp->jlink&&temp->jver==v1)
					{
						temp->jlink=node;
						break;
					}
					temp=temp->jlink;
				}
			}
		}

		if(amtg->vlist[v2].firstEdge!=node)
		{
			temp=new AMTEdgeNode();//处理v2的ilink和jlink
			temp=amtg->vlist[v2].firstEdge;
			while(temp)
			{
				if(temp->iver==v2)
				{
					if(!temp->ilink)
					{
						temp->ilink=node;
						break;
					}
					temp=temp->ilink;
				}
				else 
				{
					if(!temp->jlink&&temp->jver==v2)
					{
						temp->jlink=node;
						break;
					}
					temp=temp->jlink;
				}
			}
		}

		
		amtg->numArc++;
	}

	return OK;
}

main.cpp


#include<iostream>
#include<stdio.h>
#include <stdlib.h>
#include<string>
#include"structfun.h"

using std::string;
using std::printf;
using std::scanf;
using std::endl;
using std::to_string;

void main()
{
//图的邻接矩阵
//AdjMarGraph amg;
//CreateAdjMaxGraph(&amg);

//图的邻接表
//AdjListGraph alg;
//CreateAdjListGraph(&alg);

//图的十字链表
//OrthogonalListGraph olg;
//CreateOrthogonalListGraph(&olg);

//图的邻接多重表
AdjacencyMultipleTableGraph amtg;
CreateAdjacencyMultipleTableGraph(&amtg);

system("pause");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值