图的邻接表表示法及遍历
来源:互联网 发布:电脑microsoft windows 编辑:程序博客网 时间:2024/05/20 16:11
来看下面的一个简单的图,
那么这样的一个图,我们应该用什么存储结构来存储它呢?常用的是邻接矩阵和邻接表,这里邻接矩阵不做讲解,如下所有代码都是以邻接表作为存储结构,所以这里就只讲解下邻接表。那么什么是邻接表呢?如何构造呢?
邻接表是一种链式存储。就如上图,一共有四个顶点(分别是A,B,C,D),邻接表就是为这四个顶点的每个顶点建立一条单链表,也就是四条单链表,每个链表第一个元素就是该顶点自己。下面就以上面的图为例,具体介绍如何建立邻接表。
首先看第一条单链表,表头是顶点A。因为顶点A只与顶点B有邻接,因此,该单链表大概描述为A---->B;
再看第二条单链表,表头是B,而B与A,C,D都有邻接,故而描述为B----->A------->C------->D;
依次第三条单链表为C------>B----->D;
最后第四条单链表为D------>B----->C。
代码:
#include <stdio.h>#include <malloc.h>#define MAX_SUM 1000bool visited[MAX_SUM]= {false}; //设置标志数组struct ArcNode{ int adjvex; //该弧所指向的顶点的位置 ArcNode * next; //指向下一条弧的指针};typedef struct VNode{ char vertex; //顶点信息 ArcNode * firstarc; //指向第一条依附该顶点的弧的指针} AdjList[MAX_SUM];struct ALGraph{ AdjList adjList; int vexNum; //图的顶点数 int arcNum; //图的弧数};typedef struct node{ int data; node *next;} Node,*LinkQueueNode;typedef struct{ LinkQueueNode front; //队头指针 LinkQueueNode rear; //队尾指针} LinkQueue;bool InitQueue(LinkQueue *Q);//链队列初始化bool EnterQueue(LinkQueue *Q,int x);//入队,将数据元素x插入到队列Q中bool DeleteQueue(LinkQueue *Q,int *x);//出队,将队列Q的队头元素出队并保存到x所指的存储空间中bool IsEmpty(LinkQueue *Q);//判断链队列是否为空void CreateGraph(ALGraph *graph);//创建图void PrintGraph(ALGraph *graph);//打印图void depth_first_search(ALGraph *graph,int v);//深度优先遍历void breadth_first_search(ALGraph *graph);//广度优先遍历int main(void){ /* 请输入图的顶点数: 4 请输入图的弧数: 4 请输入4个顶点信息: ABCD 请输入4个弧的信息: 0 1 0 2 1 2 2 3 邻接表打印为: A------>C B B------>C A C------>D B A D------>C 深度优先搜索DFS:A C D B 广度优先搜索BFS:A C B D */ ALGraph graph; CreateGraph(&graph); printf("\n邻接表打印为:\n"); PrintGraph(&graph); printf("\n深度优先搜索DFS:"); for (int i = 0; i < graph.vexNum; i++) if (!visited[i])//如果没有访问 depth_first_search(&graph,i); printf("\n"); printf("\n广度优先搜索BFS:"); breadth_first_search(&graph); printf("\n"); return 0;}bool InitQueue(LinkQueue *Q)//链队列初始化{ Q->front=(LinkQueueNode)malloc(sizeof(Node)); if(Q->front!=NULL) { Q->rear=Q->front; Q->front->next=NULL; return true; } else return false;//溢出}bool EnterQueue(LinkQueue *Q,int x)//入队,将数据元素x插入到队列Q中{ LinkQueueNode NewNode; NewNode=(LinkQueueNode)malloc(sizeof(Node)); if(NewNode!=NULL) { NewNode->data=x; NewNode->next=NULL; Q->rear->next=NewNode; Q->rear=NewNode; } else return false;//溢出}bool DeleteQueue(LinkQueue *Q,int *x)//出队,将队列Q的队头元素出队并保存到x所指的存储空间中{ LinkQueueNode p; if(Q->front==Q->rear)//表示队列已空 return false; p=Q->front->next; Q->front->next=p->next;//队头元素p出队 if(Q->rear==p)//如果队中只有一个元素p,则p出队后成为空队 Q->rear=Q->front; *x=p->data; free(p);//释放存储空间 return true;}bool IsEmpty(LinkQueue *Q)//判断链队列是否为空{ return Q->front == Q->rear;}void CreateGraph(ALGraph *graph)//创建图{ printf("请输入图的顶点数:\n"); scanf("%d",&graph->vexNum); printf("请输入图的弧数:\n"); scanf("%d",&graph->arcNum); getchar(); printf("请输入%d个顶点信息:\n",graph->vexNum); for (int i = 0; i < graph->vexNum; i++) { scanf("%c",&graph->adjList[i].vertex); graph->adjList[i].firstarc = NULL; } printf("请输入%d个弧的信息:\n",graph->arcNum); int h1, h2; ArcNode * temp; for (int i = 0; i < graph->arcNum; i++)//根据输入的弧的信息构造邻接表 { scanf("%d%d",&h1,&h2); temp = new ArcNode; temp->adjvex = h2; temp->next = graph->adjList[h1].firstarc; graph->adjList[h1].firstarc = temp; temp = new ArcNode; temp->adjvex = h1; temp->next = graph->adjList[h2].firstarc; graph->adjList[h2].firstarc = temp; }}void PrintGraph(ALGraph *graph)//打印图{ for (int i = 0; i < graph->vexNum; i++) { printf("%c------>",graph->adjList[i].vertex); ArcNode *p = graph->adjList[i].firstarc; while (p) { printf("%c ",graph->adjList[p->adjvex].vertex); p = p->next; } printf("\n"); }}void depth_first_search(ALGraph *graph,int v)//深度优先遍历{ visited[v] = true; printf("%c ",graph->adjList[v].vertex); ArcNode *p = graph->adjList[v].firstarc; while (p) { if (!visited[p->adjvex]) depth_first_search(graph, p->adjvex); p = p->next; }}void breadth_first_search(ALGraph *graph)//广度优先遍历{ for (int i = 0; i < MAX_SUM; i++)//初始化访问标志数组 visited[i] = false; LinkQueue Queue; int x; InitQueue(&Queue); for (int i = 0; i < graph->vexNum; i++) if (!visited[i])//如果没有访问过 { visited[i] = true; EnterQueue(&Queue,i);//访问过的入队列 printf("%c ",graph->adjList[i].vertex); while (!IsEmpty(&Queue))//队列不为空时 { DeleteQueue(&Queue,&x);//先取出队首第一个元素,然后将第一个元素删除 ArcNode *p = graph->adjList[x].firstarc; while(p)//访问未被访问过的邻接顶点 { if (!visited[p->adjvex]) { visited[p->adjvex] = true; printf("%c ",graph->adjList[p->adjvex].vertex); EnterQueue(&Queue,p->adjvex); } p = p->next; } } }}
阅读全文
1 0
- 图的邻接表表示及遍历
- 图的邻接表表示法及遍历
- 无向图的邻接表表示法 及 深搜遍历DFS
- 图的邻接表表示及其DFS遍历
- 图的邻接表表示及其BFS遍历
- 图的广度遍历-邻接链表表示
- 图的深度遍历-邻接链表表示
- 图的邻接表表示法
- 图的邻接表表示法
- 图的邻接表表示
- 图的邻接表表示
- 图的邻接表表示
- 图的邻接表表示
- 图的邻接表表示
- 图的邻接表表示
- 图的邻接表表示
- 图的邻接表表示
- 图的邻接表表示法和遍历算法的实现
- Hdu2018 母牛的故事
- 如何解决wireshark抓包大于mtu的问题
- 关于网页消息提示音问题解决与实现
- C++容器vector的常用成员函数
- Linux(centos7)安装redis及第一个helloWorld
- 图的邻接表表示法及遍历
- 反射-通过反射写一个通用的设置某个对象的某个属性为指定的值
- 【Linux】I/O多路转接poll
- react---react创建组件的三种方式以及区别:无状态组件、工厂模式、es6语法定义
- android高级控件-下拉刷新
- 石子合并
- Solr-6.5.1配置中文分词器smartcn
- Java:发送163邮件
- Amber16和AmberTools16在CentOS 7下GPU加速版的安装