#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
*/
C语言邻接表实现图的任意两点间所有路径
最新推荐文章于 2022-01-28 21:30:00 发布