图(邻接表)

  我们先来看一个图

我们想将这个图的信息存储到邻接表中,我们需要一个数组保存节点信息,还要有一个节点用来保存与该节点相邻的节点信息.

 1 typedef struct arc_node
 2 {
 3     int pos;
 4     int distance;
 5     struct arc_node * next;
 6 } Arc_node;//保存Node节点的相邻节点信息
 7
 8 typedef struct node
 9 {
10     node_type info;
11     Arc_node * next;
12 } Node;//保存节点信息
13
14 typedef struct graph
15 {
16     Node vertexs[MAX_NUM];
17     int vertex, arc;
18 } Graph;//邻接表

如果将上面的图用邻接表存储,我们将回看到这样一幅图

每个字符后面的数字代表与它相邻的节点在数组中的位置(在Arc_node里存有权值,这里没有显示)

构造邻接表:

1)先输入节点个数及节点信息.

2)在输入某节点的相邻节点及权值.(这时,每输入一个相邻节点,就构建一个Arc_node节点,将Arc_node接到该节点的最后)

 1 void g_create(Graph * graph)
 2 {
 3     int num;
 4     int i, j, k;
 5     char c;
 6     Arc_node * tmp;
 7
 8     printf("输入节点个数:");
 9     scanf("%d", &graph->vertex);
10     getchar();
11     printf("输入顶点信息:");
12     for ( i = 0; i < graph->vertex; i++ )
13     {
14         scanf("%c", &graph->vertexs[i].info);
15         graph->vertexs[i].next = NULL;
16         getchar();
17     }
18
19     for ( i = 0; i < graph->vertex; i++ )
20     {
21         printf("输入与节点%c相邻的节点和权值,#号键结束\n", graph->vertexs[i].info);
22         for ( j = 0; j < graph->vertex; j++ )
23         {
24             scanf("%c", &c);
25             if ( c == ‘#‘ )
26             {
27                 getchar();
28                 break;
29             }
30             scanf("%d", &num);
31             getchar();
32             for ( k = 0; k < graph->vertex; k++ )
33             {
34                 if ( graph->vertexs[k].info != c )
35                     continue;
36                 if ( graph->vertexs[k].next == NULL )
37                     graph->vertexs[k].next = make_node(i, num);
38                 else
39                 {
40                     tmp = graph->vertexs[k].next;
41                     while ( tmp->next != NULL )
42                         tmp = tmp->next;
43                     tmp->next = make_node(i, num);
44                 }
45             }
46         }
47     }
48 }

深度优先遍历

邻接表的深度优先遍历根邻接矩阵的差不多.只是由于数据的存储方式有点差别,所以代码实现会有些不同,但思路还是一样的.

 1 static void dfs_graph(Graph * graph, bool visited[], const int i);
 2 void g_depth_first_search(Graph * graph)
 3 {
 4     bool visited[graph->vertex];
 5     int i;
 6
 7     for ( i = 0; i < graph->vertex; i++ )
 8         visited[i] = false;
 9
10     visited[0] = true;
11     dfs_graph(graph, visited, 0);
12 }
13
14 static void dfs_graph(Graph * graph, bool visited[], const int i)
15 {
16     Arc_node * tmp;
17     printf("%c\t", graph->vertexs[i].info);
18
19     tmp = graph->vertexs[i].next;
20     while ( tmp != NULL )
21     {
22         if ( !visited[tmp->pos] )
23         {
24             visited[tmp->pos] = true;
25             dfs_graph(graph, visited, tmp->pos);
26         }
27         tmp = tmp->next;
28     }
29 }

广度优先遍历

 1 void g_breadth_first_search(Graph * graph)
 2 {
 3     Queue queue;
 4     bool visited[graph->vertex];
 5     int pos;
 6     int i;
 7     Arc_node * tmp;
 8
 9     q_init(&queue);
10     for ( i = 0; i < graph->vertex; i++ )
11         visited[i] = false;
12
13     visited[0] = true;
14     q_push(&queue, 0);
15     while ( !q_empty(&queue) )
16     {
17         pos = q_front(&queue);
18         printf("%c\t", graph->vertexs[pos].info);
19         tmp = graph->vertexs[pos].next;
20         while ( tmp != NULL )
21         {
22             if ( !visited[tmp->pos] )
23             {
24                 visited[tmp->pos] = true;
25                 q_push(&queue, tmp->pos);
26             }
27             tmp = tmp->next;
28         }
29         q_pop(&queue);
30     }
31     printf("\n");
32 }

对于深度优先遍历和广度优先遍历的算法思路不清楚的同学请先看邻接矩阵.

graph.c

#include <stdio.h>
#include <stdlib.h>

#include "aqueue.h"

#define MAX_NUM 100
typedef char node_type;

typedef struct arc_node
{
    int pos;
    int distance;
    struct arc_node * next;
} Arc_node;//保存Node节点的相邻节点信息

typedef struct node
{
    node_type info;
    Arc_node * next;
} Node;//保存节点信息

typedef struct graph
{
    Node vertexs[MAX_NUM];
    int vertex, arc;
} Graph;//邻接表

static Arc_node * make_node(const int pos, const int distance)
{
    Arc_node * new_node = (Arc_node *)malloc( sizeof(Arc_node) );
    if ( new_node == NULL )
        exit(1);

    new_node->next = NULL;
    new_node->distance = distance;
    new_node->pos = pos;

    return new_node;
}

void g_create(Graph * graph)
{
    int num;
    int i, j, k;
    char c;
    Arc_node * tmp;

    printf("输入节点个数:");
    scanf("%d", &graph->vertex);
    getchar();
    printf("输入顶点信息:");
    for ( i = 0; i < graph->vertex; i++ )
    {
        scanf("%c", &graph->vertexs[i].info);
        graph->vertexs[i].next = NULL;
        getchar();
    }

    for ( i = 0; i < graph->vertex; i++ )
    {
        printf("输入与节点%c相邻的节点和权值,#号键结束\n", graph->vertexs[i].info);
        for ( j = 0; j < graph->vertex; j++ )
        {
            scanf("%c", &c);
            if ( c == ‘#‘ )
            {
                getchar();
                break;
            }
            scanf("%d", &num);
            getchar();
            for ( k = 0; k < graph->vertex; k++ )
            {
                if ( graph->vertexs[k].info != c )
                    continue;
                if ( graph->vertexs[k].next == NULL )
                    graph->vertexs[k].next = make_node(i, num);
                else
                {
                    tmp = graph->vertexs[k].next;
                    while ( tmp->next != NULL )
                        tmp = tmp->next;
                    tmp->next = make_node(i, num);
                }
            }
        }
    }
}

static void dfs_graph(Graph * graph, bool visited[], const int i);
void g_depth_first_search(Graph * graph)
{
    bool visited[graph->vertex];
    int i;

    for ( i = 0; i < graph->vertex; i++ )
        visited[i] = false;

    visited[0] = true;
    dfs_graph(graph, visited, 0);
}

static void dfs_graph(Graph * graph, bool visited[], const int i)
{
    Arc_node * tmp;
    printf("%c\t", graph->vertexs[i].info);

    tmp = graph->vertexs[i].next;
    while ( tmp != NULL )
    {
        if ( !visited[tmp->pos] )
        {
            visited[tmp->pos] = true;
            dfs_graph(graph, visited, tmp->pos);
        }
        tmp = tmp->next;
    }
}

void g_breadth_first_search(Graph * graph)
{
    Queue queue;
    bool visited[graph->vertex];
    int pos;
    int i;
    Arc_node * tmp;

    q_init(&queue);
    for ( i = 0; i < graph->vertex; i++ )
        visited[i] = false;

    visited[0] = true;
    q_push(&queue, 0);
    while ( !q_empty(&queue) )
    {
        pos = q_front(&queue);
        printf("%c\t", graph->vertexs[pos].info);
        tmp = graph->vertexs[pos].next;
        while ( tmp != NULL )
        {
            if ( !visited[tmp->pos] )
            {
                visited[tmp->pos] = true;
                q_push(&queue, tmp->pos);
            }
            tmp = tmp->next;
        }
        q_pop(&queue);
    }
    printf("\n");
}

int main(void)
{
    Graph graph;
    Arc_node * node;
    int i;

    g_create(&graph);

    for ( i = 0; i < graph.vertex; i++ )
    {
        printf("%c\t", graph.vertexs[i].info);
        node = graph.vertexs[i].next;
        while ( node != NULL )
        {
            printf("%d %d\t", node->distance, node->pos);
            node = node->next;
        }
        printf("\n");
    }
    printf("\n");

    g_depth_first_search(&graph);
    printf("\n");
    g_breadth_first_search(&graph);

    return 0;
}
时间: 2024-11-09 18:23:23

图(邻接表)的相关文章

【算法与数据结构】图 -- 邻接表

/************************************************************************ 边(弧)结点 -------------------------- |adjvex | info | nextarc | -------------------------- adjvex:邻接点域,该点在图中的位置 info :相关信息,比如可以保存从某顶点到该点的权值 nextac:指向下一个与该点有相同邻接点的顶点 顶点结点 ---------

数据结构----图(邻接表用法)

1.定义图的结构: 1 #define NUM_MAX 6 2 typedef struct ArcNode{ 3 int adjvex; 4 struct ArcNode * nextArc; 5 }ArcNode; //定义弧结点结构体 6 typedef struct VertexNode{ 7 int data; 8 ArcNode * firstArc; 9 }VertexNode;//定义顶点结构体 10 typedef struct { 11 VertexNode * AdjLis

一步两步学算法之图邻接表实现

图的邻接表实现 这种结构创建邻接表时添加节点较为绕 建议断点调试下看看 邻接表和邻接矩阵相比 邻接表节省空间但是很难判断两个节点之间是否有边  此种结构要在稀疏图下才划算 下面是代码 1 #define VERTEX_MAX 20 2 #include "stdio.h" 3 #include "malloc.h" 4 typedef struct edgeNode 5 { 6 int Vertex; //顶点序号 7 int weight; 8 struct ed

图-邻接表

原文地址:https://www.cnblogs.com/jundima/p/10182324.html

基于邻接表的图建立(有向图+无向图)

图的表示(建立)有两种方法: ①邻接矩阵:A(i,j)=1表示i,j存在一条边,空间复杂度O(n^2),稠密图 ②邻接表:只记录存在的边,Vector+List的数据结构,稀疏图 邻接矩阵的图建立这里不做赘述,接下来我们看一下邻接表的图建立: <1>有向图 注意理解头插入节点的过程 int n,m;//n表示城镇个数,m表示道路条数</span> struct LinkNode//列表节点 { int vex; //邻接的结点在数组中的编号 LinkNode* next; }; s

邻接表 几篇不错的解说

假设你还不知道邻接表的概念和作用etc: 请猛戳:http://baike.baidu.com/view/549594.htm?fr=aladdin struct Edge { int v; int next; }e[maxm]; memset(head,-1;sizeof(head); int c = 0; void add(int x, int y) { e[c].v = y; e[c].next = head[x]; head[x] = c++; } 图的邻接表存储 c实现:http://

邻接表求有向图各顶点的入度和出度 (图论基础)

有向图的邻接表用一个结构体LGraph存储表示,其中包括3个成员:顶点数组vertexs,顶点数vexnum和边数arcnum,其中顶点数组vertexs中每个元素都是VNode结构体变量.VNode结构体变量次年初图中每个顶点,它包含3个成员:顶点信息,出边表的表头指针和入边表的表头指针,其中后面两个成员都是ArcNode结构体类型的指针.ArcNode结构体存储边链表中的边节点,它包含两个成员:变的另一个邻接点的序号,以及指向下一个边节点的指针. #define MAXN 100 struc

邻接表 几篇不错的讲解

---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943/main ----------------------------------------------

图的邻接表表示与无环图的拓扑排序

一.  图的最常用的表示方法是邻接矩阵和邻接表. 1,邻接矩阵 邻接矩阵其实就是一个二维数组,对于每条边<u,v>,我们就令A[u][v] = 1,如果图为有权图,我们也可以令A[u][v]等于该权,这么表示的优点是非常简单,但是它的空间需求很大,如果图是稠密的,邻接矩阵是合适的表示方法,如果图是稀疏的,那这种方法就太浪费空间了,下面给出图的邻接矩阵表示例子. 2 邻接表 邻接表是图的常用储存结构之一.邻接表由表头结点和表结点两部分组成,其中图中每个顶点均对应一个存储在数组中的表头结点.如下图

浅谈数据结构之图的邻接表深度和广度优先遍历(九)

邻接矩阵是一种不错的图存储结构,但是我们发现,对于边数相对较少的图,这种结构是存在对存储空间的极大浪费的.我们知道,顺序存储结构存在预先分配内存可能造成空间浪费的问题,于是引出了链式存储的结构.同样的,我们也可以考虑对边或弧使用链式存储的方式来避免空间浪费的问题.因此,对于图的存储结构,我们同样引入了一种数组与链表相组合的存储方法,我们一般称之为邻接表. 邻接表的处理方法是这样的:(1).图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易的读取顶点的信息,更加方便:另