图的邻接表表示法及遍历

来源:互联网 发布:电脑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;                }            }        }}


原创粉丝点击