C语言邻接表实现图的任意两点间所有路径

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG 1
#if DEBUG
#define PRINTF printf
#else
#define PRINTF
#endif

//最大节点个数
#define MAX_VEX (256)
//标记节点是否被访问过(被加入路径)
char visited[MAX_VEX+1];
//记录各节点在路径中的下一节点
char path_next[MAX_VEX];
//使用数组实现栈的功能,用于记录当前走的路径
int path_record[MAX_VEX];
//表示path_record数组最大索引,来标识当前的栈顶位置
int g_idx;

//边
typedef struct edge_node
{
    int idx;
    struct edge_node *next;
}edge_node_t;

//节点
typedef struct vertex_node
{
    char data;
    edge_node_t *first_edge;
}vertex_node_t, vertex_node_list[MAX_VEX];

//图
typedef struct graph
{
    vertex_node_list list;
    int num_vex;
    int num_edge;
}graph_t;

void print_graph(graph_t *g)
{
    int i;
    edge_node_t *p;

    for(i=0; i<g->num_vex; i++)
    {
        printf("<%d> : %c ", i, g->list[i].data);
        if(NULL == g->list[i].first_edge)
            printf(" >> NULL");
        else
        {
            for(p=g->list[i].first_edge; p!=NULL; p=p->next)
            {
                printf(" >> <%d> %c", p->idx, g->list[p->idx].data);
            }
        }
        printf("\n");
    }
}

void free_graph(graph_t *g)
{
    int i;
    edge_node_t *p, *q;

    for(i=0; i<g->num_vex; i++)
    {
        p = g->list[i].first_edge;
        while(p)
        {
            q = p->next;
            free(p);
            p = q;
        }
    }
}

int create_graph(graph_t *g)
{
    int i, j, k;
    edge_node_t *p, *q;
    int ret;

    //输入节点数和边数
    PRINTF("input num of vertex and num of edge : ");
    ret = scanf("%d %d\n", &(g->num_vex), &(g->num_edge));
    PRINTF("ret = %d, num_vex : %d, num_edge : %d\n", ret, g->num_vex, g->num_edge);

    //输入节点信息
    PRINTF("input data of vertex:\n");
    for(i=0; i<g->num_vex; i++)
    {
        PRINTF("vertex %d : ", i+1);
        ret = scanf("%c\n", &(g->list[i].data));
        PRINTF("ret = %d, %d : %d\n", ret, i, g->list[i].data);
        g->list[i].first_edge = NULL;
    }

    //输入边信息;当前实现按照无向图创建
    for(k=0; k<g->num_edge; k++)
    {
        PRINTF("input the index of (vi, vj) : ");
        ret = scanf("%d %d\n", &i, &j);
        PRINTF("ret : %d, i : %d, j : %d\n", ret, i, j);
        p = (edge_node_t *)malloc(sizeof(edge_node_t));
        memset(p, 0x0, sizeof(edge_node_t));
        p->idx = j;
#if 0
        p->next = g->list[i].first_edge;
        g->list[i].first_edge = p;
#else
        if(g->list[i].first_edge == NULL)
            g->list[i].first_edge = p;
        else
        {
            for(q=g->list[i].first_edge; q->next!=NULL; q=q->next);
            q->next = p;
        }
#endif
        p = (edge_node_t *)malloc(sizeof(edge_node_t));
        memset(p, 0x0, sizeof(edge_node_t));
        p->idx = i;
#if 0
        p->next = g->list[j].first_edge;
        g->list[j].first_edge = p;
#else
        if(g->list[j].first_edge == NULL)
            g->list[j].first_edge = p;
        else
        {
            for(q=g->list[j].first_edge; q->next!=NULL; q=q->next);
            q->next = p;
        }
#endif

    }
}

//查找与当前节点连接的下一个可用的节点
edge_node_t *neighbour(graph_t *g, int idx)
{
    edge_node_t *p;

    p = g->list[idx].first_edge;

    while(NULL != p)
    {
        if(visited[p->idx] == 1)//已在路径中
        {
            p = p->next;
        }
        else
        {
            if(-1 == path_next[idx])//未被路径访问过
            {
                while(p!=NULL && visited[p->idx]==1)
                    p = p->next;
                return p;
            }
            else if(p->idx == path_next[idx])//被上一次路径访问过
            {
                p = p->next;
                while(p!=NULL && visited[p->idx]==1)
                    p = p->next;
                return p;
            }
            else//被以前的路径访问过
            {
                p = p->next;
            }
        }
    }
}

/*****************************************************************************
 函 数 名  : all_path
 功能描述  : 在图g中查找起始节点start到结束节点end之间的所有路径并输出
 输入参数  : graph_t *g   图的邻接表存储结构
             int start   起始节点
             int end     结束节点
 输出参数  : 无
 返 回 值  : 

*****************************************************************************/
void all_path(graph_t *g, int start, int end)
{
    int i, cur_vex;
    edge_node_t *p;

    while(g_idx >= 0)
    {
        cur_vex = path_record[g_idx];
        if(cur_vex == end)//已走到结束节点,输出完整路径
        {
            PRINTF("%d -> %d : ", start, end);
            for(i=0; i<=g_idx; i++)
            {
                if(i == 0)
                    PRINTF("<%d> %c", path_record[i], g->list[path_record[i]].data);
                else
                    PRINTF(" >> <%d> %c", path_record[i], g->list[path_record[i]].data);
            }
            PRINTF("\n");
            //结束节点出栈
            visited[end] = 0;
            path_record[g_idx] = -1;
            path_next[end] = -1;
            g_idx--;
        }
        else
        {
            p = neighbour(g, cur_vex);
            if(p != NULL)
            {
                //有可走的路径下一跳,当前节点入栈
                path_next[cur_vex] = p->idx;
                g_idx++;
                path_record[g_idx] = p->idx;
                visited[p->idx] = 1;
            }
            else
            {
                //没有可走的路径下一跳,当前节点出栈
                visited[cur_vex] = 0;
                path_record[g_idx] = -1;
                path_next[cur_vex] = -1;
                g_idx--;
            }
        }
    }
}

int main()
{
    graph_t g;
    int start, end;
    int ret, i;

    memset(&g, 0x0, sizeof(g));
#if DEBUG
    freopen("data.txt", "r", stdin);
#endif

    create_graph(&g);
#if DEBUG
    PRINTF("[%s][%d] print_graph : \n", __FUNCTION__, __LINE__);
    print_graph(&g);
#endif

    //初始化
    for(i=0; i<g.num_vex; i++)
    {
        visited[i] = 0;
        path_next[i] = -1;
        path_record[i] = -1;
    }
    g_idx = 0;

    //输入起始和结束节点
    PRINTF("input start and end node index : ");
    ret = scanf("%d %d\n", &start, &end);
    PRINTF("ret : %d, start : %d, end : %d\n", ret, start, end);

    //起始节点入栈
    path_record[g_idx] = start;
    visited[start] = 1;
    all_path(&g, start, end);

    free_graph(&g);
    return 0;
}

// 样例输入:
/*
8 9
a
b
c
d
e
f
g
h
0 1
0 2
1 3
1 4
3 7
4 7
2 5
2 6
5 6
3 6
*/

/*
8 9
0
1
2
3
4
5
6
7
0 1
0 2
1 3
1 4
3 7
4 7
2 5
2 6
5 6
3 6
*/

/*
9 11
0
1
2
3
4
5
6
7
8
0 1
0 2
1 3
1 4
3 7
4 7
2 5
2 6
5 6
5 8
6 8
3 6
*/

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值