图的存储方式有很多种,这里是以邻接表存储为例实现的。图的基本操作包括初始化一个空图、插入一节点、插入条边、深度优先遍历、广度优先遍历、销毁图等

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR -1
#define MAX_VEX 10//最大顶点数
typedef int InfoType;
typedef char VexType;//顶点的类型
typedef int WeightType;//权值的类型

图的种类(有向图、无向图、加权有向图、加权无向图),采用枚举法

typedef enum
{DG = 1, AG, WDG, WAG//有向图  无向图  带权有向图  带权无向图
}GraphKind;

邻接表的前半部分是顺序表,所以定义一个顺序表的结构体

typedef struct VexNode
{VexType data;//顶点的值int indegree;//顶点的度LinkNode *firstarc;//指向第一个表节点,有向图是入度或出度或没有
}VexNode;//顶点节点类型定义

邻接表后半部分是链表,所以定一个链表的结构体

typedef struct LinkNode
{int adjvex;//邻接点在头结点数组中的位置(下标)InfoType info;//节点信息   如权值struct LinkNode *nextarc;//指向下一个表节点
}LinkNode;

接下来定义图的结构体

typedef struct
{GraphKind kind;int vexnum;//顶点的个数VexNode AdjList[MAX_VEX];//头结点的类型的数组
}ALGraph;

在图的一系列基本操作中需要队列的帮助

//队列的结构体
typedef struct SqQueue
{VexType array[MAX_VEX];int front;int rear;
}SqQueue;//初始化一个空队列
SqQueue Creat_SqQueue()
{SqQueue Q;Q.front = 0;Q.rear = 0;return Q;
}//入队列  若成功返回1  否则返回-1
int InsertQueue(SqQueue *Q, VexType e)
{if ((Q->rear+1)%MAX_VEX == Q->front){printf("The queue is full.\n");return ERROR;}else{Q->array[Q->rear] = e;Q->rear = (Q->rear + 1) % MAX_VEX;//printf("Insert success!\n\n");}return OK;
}//出队列 若成功返回弹出的元素  若不成功返回-1
VexType DeletaQueue(SqQueue *Q)
{VexType e = 0;if (Q->front == Q->rear){printf("This queue is empty!\n");return ERROR;}else{e = Q->array[Q->front];Q->front = (Q->front + 1) % MAX_VEX;//printf("Delete success!\n");}return e;
}

建立一个空图

ALGraph CreatGraph() {ALGraph G;int i;//循环变量int a = 0;printf("1.DG\n2.AG\n3.WDG\n4.WAG\n");printf("please enter the type of graph(according to the code):\n");scanf("%d", &a);//确定图的类型switch (a){case 1:G.kind = DG;break;case 2:G.kind = AG;break;case 3:G.kind = WDG;break;case 4:G.kind = WAG;break;default:printf("The type of the graph is error\n");break;}G.vexnum = 0;//结点个数置为0for (i = 0; i < MAX_VEX; i++)//把所有节点的度置为0{G.AdjList[i].indegree = 0;G.AdjList[i].firstarc = NULL;}return G;
}

插入节点时需要判断节点是否在,若不存在插入,如存在插入失败

//定位节点  若存在返回1  若不存在返回-1
int LocateVex(ALGraph *G, VexType v) {int i = 0;int a = 0;printf("v = %c\n", v);for (i = 0; i < G->vexnum; i++){if (G->AdjList[i].data == v){a++;break;}}if (a == 0){return ERROR;}return OK;
}

在图中插入一个节点

void InsertVex(ALGraph *G){int res = 0;if (G->vexnum + 1 == MAX_VEX){printf("The graph is overflow!\n");}else{VexType u = '\0';printf("please enter data:\n");getchar();scanf("%c", &u);res = LocateVex(G, u);if (res == -1)//没有节点   添加{G->AdjList[G->vexnum].data = u;G->AdjList[G->vexnum].firstarc = NULL;G->vexnum++;//printf("insert vertex success\n");}else{printf("insert vertex fail\n");}}
}

在图中插入一条边时,要判断图的类型,不同的类型,插入操作是不一样的

void InsertArc(ALGraph *G) {if (G->kind == DG)//有向图{LinkNode *p;LinkNode *r;int tail = 0;//弧尾(起点)int head = 0;//弧头(终点)p = (LinkNode *)malloc(sizeof(LinkNode));printf("please enter the tail:");scanf("%d", &tail);printf("please enter the head:");scanf("%d", &head);if (tail < G->vexnum && head < G->vexnum){p->adjvex = head;p->nextarc = NULL;p->info = 0;r = G->AdjList[tail].firstarc;p->nextarc = r;G->AdjList[tail].firstarc = p;G->AdjList[tail].indegree++;printf("insert arc success\n");}else{printf("vertex is not exit.");}}else if(G->kind == AG)//无向图{LinkNode *p;LinkNode *q;LinkNode *r;LinkNode *s;int tail = 0;int head = 0;p = (LinkNode *)malloc(sizeof(LinkNode));q = (LinkNode *)malloc(sizeof(LinkNode));s = (LinkNode *)malloc(sizeof(LinkNode));printf("please enter the tail:");scanf("%d", &tail);printf("please enter the head:");scanf("%d", &head);if (tail < G->vexnum && head < G->vexnum){p->adjvex = head;p->info = 0;p->nextarc = NULL;r = G->AdjList[tail].firstarc;p->nextarc = r;G->AdjList[tail].firstarc = p;s->adjvex = tail;s->info = 0;q = G->AdjList[head].firstarc;s->nextarc = q;G->AdjList[head].firstarc = s;G->AdjList[tail].indegree++;G->AdjList[head].indegree++;printf("insert arc success\n");}else{printf("vertex is not exit.\n");}}else if (G->kind == WDG)//加权有向图{LinkNode *p;LinkNode *r;int info = 0;int tail = 0;//弧尾(起点)int head = 0;//弧头(终点)p = (LinkNode *)malloc(sizeof(LinkNode));printf("please enter the tail:");scanf("%d", &tail);printf("please enter the head:");scanf("%d", &head);printf("please enter the information:");scanf("%d", &info);if (tail < G->vexnum && head < G->vexnum){p->adjvex = head;p->nextarc = NULL;p->info = info;r = G->AdjList[tail].firstarc;p->nextarc = r;G->AdjList[tail].firstarc = p;G->AdjList[tail].indegree++;printf("insert arc success\n");}else{printf("vertex is not exit.\n");}}else if(G->kind == WAG)//加权无向图{LinkNode *p;LinkNode *q;LinkNode *r;LinkNode *s;int info = 0;int tail = 0;int head = 0;p = (LinkNode *)malloc(sizeof(LinkNode));q = (LinkNode *)malloc(sizeof(LinkNode));s = (LinkNode *)malloc(sizeof(LinkNode));printf("please enter the tail:");scanf("%d", &tail);printf("please enter the head:");scanf("%d", &head);printf("please enter the information:");scanf("%d", &info);if (tail < G->vexnum && head < G->vexnum){p->adjvex = head;p->nextarc = NULL;p->info = info;r = G->AdjList[tail].firstarc;p->nextarc = r;G->AdjList[tail].firstarc = p;s->adjvex = tail;s->info = info;q = G->AdjList[head].firstarc;s->nextarc = q;G->AdjList[head].firstarc = s;G->AdjList[tail].indegree++;G->AdjList[head].indegree++;printf("insert arc success\n");}else{printf("vertex is not exit.\n");}}else{printf("The type of the graph is error\n");}
}

图的深度优先遍历

void DFSTraverse(ALGraph *G, int v, int visit[]) {LinkNode *p;if (visit[v] == 0){printf("%c\n", G->AdjList[v].data);visit[v] = 1;p = G->AdjList[v].firstarc;while (p != NULL){if (visit[p->adjvex] == 0){DFSTraverse(G, p->adjvex, visit);}p = p->nextarc;}}
}

图的广度优先遍历

void BFSTraverse(ALGraph *G){int i = 0;//循环变量int k = 0;//循环变量SqQueue Q = Creat_SqQueue();//visited为访问标志数组,为0则该节点没被访问过,为1则被访问过int visited[MAX_VEX];LinkNode *p;for (i = 0; i < MAX_VEX; i++)//访问标志初始化{visited[i] = 0;}//广度优先遍历图for (k = 0; k < G->vexnum; k++){if (visited[k] == 0)//若该节点没有被访问过{InsertQueue(&Q, k);visited[k] = 1;if (G->AdjList[k].firstarc != NULL){p = G->AdjList[k].firstarc;while (p != NULL){if(visited[p->adjvex] == 0){InsertQueue(&Q, p->adjvex);visited[p->adjvex] = 1;}p = p->nextarc;}}}else//若该节点被访问过{if (G->AdjList[k].firstarc != NULL){p = G->AdjList[k].firstarc;while (p != NULL){if(visited[p->adjvex] == 0){InsertQueue(&Q, p->adjvex);visited[p->adjvex] = 1;}p = p->nextarc;}}}}while (Q.front != Q.rear)//循环弹出队列中的元素{printf("%c\n", G->AdjList[DeletaQueue(&Q)].data);}
}

销毁一个图

int DestroyGeaph(ALGraph *G) {int i = 0;//循环变量for (i = 0; i < G->vexnum; i++){G->AdjList[i].data = 0;G->AdjList[i].indegree = 0;G->AdjList[i].firstarc = NULL;}G->vexnum = 0;return OK;
}

以邻接表的形式输出图

void OutPutGraph(ALGraph G)
{int i = 0;//循环变量printf("value\tindegree\tfirstarc\n");for (i = 0; i < G.vexnum; i++){printf("%c\t", G.AdjList[i].data);printf("%d\t\t", G.AdjList[i].indegree);LinkNode *p;p = G.AdjList[i].firstarc;while (p != NULL){printf("->");printf("%c \t", G.AdjList[p->adjvex].data);p = p->nextarc;}printf("\n");printf("----------------------\n");}
}

示例:

运行结果:

以上就是图的基本操作了,主方法就不写了,大家根据可以自己的需要写,希望大家看了以后能帮得上忙。

图的邻接表存储及基本操作相关推荐

  1. 图的邻接表存储实现(第七章 P163)

    图的邻接表存储结构: 下图分别是有向图和无向网的的邻接表存储结构.要注意的是,为了提高效率,程序中的基本操作函数 CreateGraph()产生链表时总是在表头插入结点. 所以,对于给定的图,即使它的 ...

  2. mysql 邻接表_图的邻接表存储结构详解

    通常,图更多的是采用链表存储,具体的存储方法有 3 种,分别是邻接表.邻接多重表和十字链表. 本节先讲解图的邻接表存储法.邻接表既适用于存储无向图,也适用于存储有向图. 在具体讲解邻接表存储图的实现方 ...

  3. 数据结构——图的邻接表存储

    数据结构--图的邻接表存储 功能实现: (1)图的邻接矩阵的储存 (2)深度优先遍历 (3).广度优先遍历 (4)求结点的度 (5)判断图是否连通 (6)求最小生成树 参考代码 #include &l ...

  4. 图的邻接表存储与深度优先遍历代码实现

    Graph.h Vnode结构成员firstarc在定义时赋初值NULL,在Visual Stdio 2013下编译通过,VC6.0就不行(非静态数据成员不能初始化) #include <std ...

  5. java邻接图_Java数据结构 - 图(邻接表存储)

    邻接表 相比邻接矩阵,邻接表要更加节省空间. 邻接表存储 本文将介绍邻接表存储有向带权图.图的例子如下. 图 介绍一下邻接表 上面的图对应的邻接表如下图所示: 邻接表 前面的数组存储的是所有的顶点,每 ...

  6. 【数据结构/C语言版】【图】邻接表存储

    邻接表 邻接表由第一数列的表头和每个表头对应连接的链表构成.每一个表头都是一个单链表表头.表头作为出发点,其链表内元素就是出发点可直接到达的目标点(也可以附加边权). 图邻接表存储优势: 1.支持有向 ...

  7. 分别采用深度优先遍历和广度优先遍历判断是否存在由vi到vj的路径,图用邻接表存储

    分析:         采用深度优先:我们从vi顶点开始进行深度遍历,若存在路径则必然可以走到vj顶点处:         采用广度优先:同样从vi顶点开始进行广度遍历,若存在则必然可以走到vj顶点处 ...

  8. 图采用邻接表存储,设计一个算法,判断顶点i和顶点j(i!=j)之间是否有路径

    算法思想:只要以i为起点,进行遍历,只要遍历过程中遇到了j,就证明有路径. 算法代码 int DFSTravel(AGraph *G,int i,int j) {int k;for(k=0;k< ...

  9. 《数据结构》-图的邻接表表示法(四)

    邻接表表示法(链式) 存储定义: 顶点:按编号顺序将顶点数据存储在一维数组中 关联同一顶点的边(以顶点为尾的弧):用线性链表存储 无向图的邻接表 例如,如下无向图 则它的邻接表为 无向图邻接表的特点: ...

最新文章

  1. 如何向列表中添加数据值(管理员篇)
  2. BizTalk学习笔记系列之二:实例说明如何使用BizTalk
  3. vpython 贞测碰撞_7、Pygame碰撞检测
  4. 【算法设计与分析】02 货郎问题与计算复杂性理论
  5. 追踪多省网络故障:域名解析瘫痪后的连锁反应
  6. 带你掌握不同平台下,探索JDK源码所需的native方法
  7. Flink学习笔记03:将项目打包提交到Flink集群上运行(Java版)
  8. 学python多大年龄可以学车_2020想学车的注意,关于学车的年龄问题,你都了解吗?...
  9. 【引用】在VB6.0中实现弹出式菜单的几种方法
  10. 创建一个1000w个随机浮点数的数组
  11. Linux命令之lsof
  12. NOIP 2005 等价表达式 (TYVJ P1060)
  13. html里的音频插件,html5音频播放插件
  14. 办公室常用计算机常识,这10个办公必备的电脑小技巧,让你事半功倍
  15. matlab状态反馈控制器设计,H无穷的状态反馈控制器设计
  16. 浦东人大常委会副主任刘宇青一行莅临零数科技指导工作
  17. 嵌入式linux学习路径--新手入门篇
  18. python-opencv控制鼠标操作
  19. 在folium中使用高德底图/百度底图/google底图
  20. 简单抽奖软件java程序设计

热门文章

  1. 嘉立创PCB打样不是5元而是23元?
  2. google vr 入门之制作简易的VR播放器(二)
  3. Anti-recall 防撤回神器 -- Android 免root查看撤回消息和闪照 官网
  4. mod_wsgi.so+django+python部署了几天。。惭愧惭愧
  5. 微信支付服务器端demo,004-移动支付02-微信支付-服务器开发
  6. Unity3D 场景切换异步加载进度
  7. python短信平台_Python短信接口demo
  8. PnP问题之P3P求解方式
  9. 树形结构根据指定节点id,查询所有上级
  10. [看毛片算法][KM]zoj 3615:Choir II