数据结构-图-邻接表

本文介绍了图的邻接表存储方式,针对有向图和无向图,阐述了邻接表的结构特点,包括邻接点域、链域和数据域的组成,并提供了创建、插入、删除等操作的伪代码。邻接表适用于稀疏图的存储,避免了不必要的空间浪费。
摘要由CSDN通过智能技术生成

使用邻接矩阵有它的优点:易于求结点度,求邻接点,易判断两点间是否有弧相连。但不利于稀疏图的存储,因弧不存在时也要存储相应信息。且要预分配足够大空间。

下面来介绍使用邻接表的方式来存储图。

在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附与顶点vi的边,对有向图是以顶点vi为尾的弧。每个顶点以3个域组成,其中邻接点域(adjvex)指示与顶点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的结点,数据域(Info)存储和边或弧相关的信息,如权值等。每个链表上附设一个表头结点。在表头结点中,除了设有链域(firstarc)指向链表中第一个结点之外,还设有存储顶点vi的名或其他有关信息的数据域(data)。

首先是辅助宏的定义:

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define UNDERFLOW -2
#define MAX_INFO 50
#define MVNUM 100
#define maxn 100
#define maxm 100
#define INFINITY 32767  //一定要很大
typedef int Status;
typedef char VertexType;
typedef char InfoType;
typedef enum{DG,DN,UDG,UDN} GraphKind; //图类型  有向图,无向图,有向网,无向网

邻接表的存储结构定义:

typedef struct ArcNode{//弧结点
   int adjvex;
   InfoType *Info; //弧的附加信息
   double adj; //邻接数 1或w
   struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode{ //图结点
   VertexType data;
   ArcNode *firstarc; //头结点
}VNode,*AdjList;
//图的邻接表存储结构定义
typedef struct{
   AdjList vertices; //邻接表
   int vexnum,arcnum; //图结点数,弧数
   GraphKind kind; //图类型
}ALGraph;

若G中存在顶点v 返回v的位置 否则返回-1.

int LocateVex(ALGraph &G,VertexType v){
   //若G中存在顶点v 返回v的位置 否则返回-1
   for(int i=0;i<G.vexnum;i++)
       if(G.vertices[i].data==v)
           return i;
   return -1;
}

图的创建.输入图的种类和边顶点构造图.

Status CreateGraph(ALGraph &G){
    //图的创建
    //输入图的种类和边顶点构造图
    scanf("%d",&G.kind);
    switch(G.kind){
       case DG: return CreateDG(G);
       case DN: return CreateDN(G);
       case UDG: return CreateUDG(G);
       case UDN: return CreateUDN(G);
       default: return ERROR;
   }
}

创建有向图G.

Status CreateDG(ALGraph &G){
    //创建有向图G
   int i,j,k;
   VertexType v1,v2;
   ArcNode *arc;
   scanf("%d %d",&G.vexnum,&G.arcnum);
   if(!(G.vertices=(AdjList)malloc(G.vexnum*sizeof(VNode)))) //创建邻接表
       exit(OVERFLOW);
   for(i=0;i<G.vexnum;i++){
       scanf(" %c",&G.vertices[i].data); //输入结点
       G.vertices[i].firstarc=NULL;
   }
   for(k=0;k<G.arcnum;k++){ //输入弧
       scanf(" %c %c",&v1,&v2);
       i=LocateVex(G,v1);
       j=LocateVex(G,v2);
       if(!(arc=(ArcNode *)malloc(sizeof(ArcNode))))
           exit(OVERFLOW);
       arc->adjvex=j;
       arc->adj=1.0;
       arc->Info=NULL;
       arc->nextarc=G.vertices[i].firstarc; //插入到开始位置 邻接点与输入逆序排列
       G.vertices[i].firstarc=arc;
   }
   return OK;
}
这是我的作业。。。。希望对各位有#include <stdio.h> #include <malloc.h> #include <stdlib.h> #define SIZE (xsize*ysize+1) //一系列全局变量便于传递参数 int *location,*way, xsize,ysize,firstx,firsty, noworder; int getnum (void);//取数函数,取数成功返回1,否则返回-1 int init (void); //初始化函数,申请数组空间,以及初始化数组, //申请成功返回1,否则返回-1 int play (void); //下棋函数,下棋成功返回1,否则返回-1 int back (void); //悔棋函数,悔棋成功返回1,否则返回-1 void print (void);//输出函数,顺序输出马踩的棋盘一维坐标 //////////////////////////// void main () { int canget,caninit,canplay,canback; do canget=getnum(); while(canget==-1); caninit=init(); if(caninit==-1) exit (0);//终止程序运行 for (;noworder<SIZE-1;) { if(way[location[noworder]]>0 && way[location[noworder]]<=8) { canplay=play(); if(canplay==-1) way[location[noworder]]++;//当前方法不可行,改变方法 } else { canback=back(); if(canback==-1) { printf("不可能遍历整个棋盘!\n"); getchar();getchar(); exit (0);//当程序不能再悔棋时终止程序运行 } else way[location[noworder]]++; //当前方法不可行,改变方法 } } if(noworder==SIZE-1)//已经遍历整个棋盘 print(); getchar();getchar(); } //////////////////////////// int getnum() { printf("输入棋盘规格(假定无0点)和入口坐标:\n"); printf("输入棋盘规格xsize="); scanf("%d",&xsize); printf("输入棋盘规格ysize="); scanf("%d",&ysize); printf("输入入口坐标x="); scanf("%d",&firstx); printf("输入入口坐标y="); scanf("%d",&firsty); if (firstx>xsize || firsty>ysize || firstx<=0 || firsty<=0 || xsize <3 || ysize<3) { printf("输入有误,重新输入:\n\n\a"); return -1; } else return 1; } //////////////////////////// int init (void) { location=(int *)malloc(sizeof(int)*SIZE); way=(int *)malloc(sizeof(int)*SIZE); if(location==NULL || way==NULL) { printf("系统申请内存空间失败!程序执行终止!\a"); return -1; } for(int i=0;i<SIZE;i++)//初始化数组 { way[i]=0; location[i]=0; } noworder=1; location[1]=(firsty-1)*xsize+firstx; way[location[1]]=1; return 1; } //////////////////////////// void print(void) { printf("\n\n可以遍历,顺序如下:\n\n"); for (int i=1;i<SIZE;i++) { printf("%3d-->",location[i]); printf("OK\n"); } } //////////////////////////// int play() { int x,y,nextlocation; //一维坐标值à二维坐标值 x=location[noworder] % xsize; if(x==0) x=xsize; y=(location[noworder]-x)/xsize+1; switch (way[location[noworder]]) { case 1 : x+=2;y-=1;break; case 2 : x+=2;y+=1;break; case 3 : x+=1;y+=2;break; case 4 : x-=1;y+=2;break; case 5 : x-=2;y+=1;break; case 6 : x-=2;y-=1;break; case 7 : x-=1;y-=2;break; case 8 : x+=1;y-=2;break; } nextlocation = xsize*(y-1)+x; if (x>xsize || y>ysize || x<=0 || y<=0 || way[nextlocation]!=0)//越界或重复 return -1; else//下棋 { noworder++; location[noworder] = nextlocation; way[location[noworder]]=1; return 1; } } //////////////////////////// int back (void) { if(noworder==1)//不能再悔棋,不能遍历 return -1; else { way[location[noworder]]=0;//注意不能搞错语句顺序 location[noworder]=0; noworder--; return 1; } }用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值