邻接表实现图的储存,遍历

邻接表是图的一种链式存储结构。对图的每个顶点建立一个单链表(n个顶点建立n个单链表),第i个单链表中的结点包含顶点Vi的所有邻接顶点。又称链接表。

1.在有向图的邻接表中不易找到指向该顶点的弧。

2.在有向图的邻接表中,对每个顶点,链接的是以该顶点为弧尾的邻接点。

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define OK 1
#define ERROR 0
 
typedef struct node//表结点 一个顶点对应一个单链表(链表的节点为该顶点的邻接点)vex表示与顶点邻接的点在图中的位置 
{
    int vex;
    struct node *next;
}Node;
 
typedef struct head//头顶点  每个顶点对应一个头结点 first指向第一条边
{
    int data;
    Node *first;
}VNode;
 
typedef struct   //边数 顶点数  存储顶点的数组
{
    VNode list[MAX];
    int v, e;
}Graph;
 
 
void CreatReverseGraph(Graph *G)//有向图逆邻接表
{
    int s, e, i;
    Node *temp;
 
    scanf("%d%d", &(*G).v, &(*G).e);
 
    for (i = 0; i < (*G).v; i++)
    {
        (*G).list[i].first = (Node *)malloc(sizeof(Node));
        ((*G).list[i].first)->next = NULL;
        (*G).list[i].data = 0;
    }
     
    for (i = 0; i < (*G).e; i++)
    {
        scanf("%d%d", &s, &e);
        temp = (Node *)malloc(sizeof(Node));
        temp->vex = s;
        temp->next = ((*G).list[e].first)->next;
        ((*G).list[e].first)->next = temp;
        (*G).list[e].data += 1;
    }
 
}
 
void CreatGraph(Graph *G)//无向图的逆邻接表
{
    int i;
    int s, e;
    Node *temp;
 
    scanf("%d%d", &(*G).v, &(*G).e);
     
    for (i = 0; i < (*G).v; i++)
    {
        (*G).list[i].first = (Node *)malloc(sizeof(Node));
        ((*G).list[i].first)->next = NULL;
        (*G).list[i].data = 0;
    }
    for (i = 0; i < (*G).e; i++)
    {
        scanf("%d%d", &s, &e);
        temp = (Node *)malloc(sizeof(Node));
        temp->vex = e;
        temp->next = ((*G).list[s].first)->next;
        ((*G).list[s].first)->next = temp;
        (*G).list[s].data += 1; 
         
        temp = (Node *)malloc(sizeof(Node));
        temp->vex = s;
        temp->next = ((*G).list[e].first)->next;
        ((*G).list[e].first)->next = temp;
        (*G).list[e].data += 1;
    }
}
 
int FirstVertix(Graph G, int v)//返回顶点v的第一个邻接顶点
{
    Node *temp;
    temp = (G.list[v].first)->next;
     
    if (!temp)
        return -1;
    return temp->vex;
}
 
int NextVertix(Graph G, int v, int w)//返回顶点v相对于w的下一个邻接顶点
{
    Node *temp;
    temp = (G.list[v].first);
     
    for (temp = temp->next; temp; temp = temp->next)
        if (temp->vex == w)
            break;
    if (temp->next == NULL || !temp)
        return -1;
    return temp->next->vex;
 
}
 
void DFS(Graph G, int i, int *visit)//深度优先搜索
{
    int k;
     
    visit[i] = 1;
     
    printf("%d ", i + 1);
    for (k = FirstVertix(G, i); k >= 0; k = NextVertix(G, i, k))//遍历所有邻接顶点,若该顶点未访问,递归深度搜索
        if (!visit[k])
        {
            printf("(%d  %d)\n", i + 1, k + 1);
            DFS(G, k, visit);
        }
}
 
 
void DFSVisit(Graph G)
{
    int visit[MAX];
    int i;
 
    memset(visit, 0, sizeof(int) * G.v);//初始话标记数组visit
     
    for (i = 0; i < G.v; i++)
    {
        if (!visit[i])
            DFS(G, i, visit);
    }
}
 
void BFSVisit(Graph G)//广度优先搜索
{
    int visit[MAX];
    int queue[MAX];//队列存储顶点
    int front = 0, rear = 0;
    int i, j, k;
 
    memset(visit, 0, sizeof(int) * G.v);
     
    for (i = 0; i < G.v; i++)
    {
        if (!visit[i])//访问顶点并将该顶点入队
        {
            visit[i] = 1;
            printf("%d\n", i + 1);
            queue[rear++] = i;
        }
        while (rear != front)
        {
            k = queue[front++];//出队
            for (j = FirstVertix(G, k); j >= 0; j = NextVertix(G, k, j))//遍历该顶点所有邻接顶点
                if (!visit[j])
                {
                    visit[j] = 1;
                    printf("%d ", j + 1);
                    printf("(%d  %d)\n", k + 1, j + 1);
                    queue[rear++] = j;
                }
        }
    }
}
     
 
int main()
{
    Graph G;
 
    CreatGraph(&G);
    //CreatReverseGraph(&G);
    printf("The DFS is:\n");
    DFSVisit(G);
    printf("\nThe BFS is:\n");
    BFSVisit(G);
    return 0;
}



转载于:https://www.cnblogs.com/tham/p/6827371.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值