最近學習了圖的廣度優先搜索的介紹,爲了加深理解就自己動手用C語言實現了下面這個路徑問題,代碼全部在codeblocks下測試通過。
給定起點和終點和中間所有路徑的時間,求
1)所有從起點出發到達終點的所有路徑
2)從起點到終點的最短路徑
設計思路:
1)用節點來表示各個站點
2)用連接兩個相鄰節點的連接來表示他們之間的路徑
3)從起點到終點遍歷一遍用遞歸的辦法可以計算出所有可能的路徑和它們的時間
主要數據結構和函數:
typedef struct _graph_node_key
{
char *name;
}NODE_KEY;
typedef struct _graph_node GRAPH_NODE;
typedef struct _graph_route_list GRAPH_ROUTE_LIST;
typedef struct _graph_link
{
void *pdata;
GRAPH_NODE *link_to;
struct _graph_link *next;
}GRAPH_LINK;
typedef struct _graph_node
{
NODE_KEY key;
void *pdata;
GRAPH_LINK *link_list;
}GRAPH_NODE;
typedef void (*LINK_INFO_PRINT_FUNC)(void *info) ;
typedef int (*LINK_KEY_CALC_FUNC)(void *info) ;
typedef struct _graph_route{
GRAPH_NODE *node;
GRAPH_LINK *link;
int route_key;
struct _graph_route *next;
}GRAPH_ROUTE;
typedef struct _graph_route_list
{
GRAPH_ROUTE *route_head;
int cost;
struct _graph_route_list *next;
}GRAPH_ROUTE_LIST;
typedef struct _graph
{
int node_dsize;
int link_dsize;
GRAPH_NODE *root;
GRAPH_ROUTE_LIST *route_list_head;
LINK_INFO_PRINT_FUNC link_print_func;
LINK_KEY_CALC_FUNC link_key_func;
}GRAPH;
void graph_print(GRAPH *g);
void graph_traverse(GRAPH *g);
GRAPH* graph_init(int node_dsize,int link_dsize,LINK_INFO_PRINT_FUNC lp_func,LINK_KEY_CALC_FUNC lk_func);
GRAPH_NODE* graph_node_init(NODE_KEY key,void *pdata,int dsize);
RV graph_add_root(GRAPH *g,GRAPH_NODE *node);
RV graph_node_linkto(GRAPH_NODE *from,GRAPH_NODE *to,void *pdata,int dsize);
void graph_calc_route_list(GRAPH_ROUTE_LIST *route_list);
函數實現:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "define.h"
#include "graph.h"
static void node_print(GRAPH *g,GRAPH_NODE *node,int level);
static void node_traverse(GRAPH *g,GRAPH_ROUTE_LIST *route_list,GRAPH_NODE *node);
static void level_print(int level)
{
while(level--)printf("\t");
return;
}
static void link_print(GRAPH *g,GRAPH_LINK *link,int level)
{
level_print(level);
g->link_print_func(link->pdata);
return;
}
static void link_list_print(GRAPH *g,GRAPH_LINK *link_list,int level)
{
level++;
while(link_list)
{
link_print(g,link_list,level);
node_print(g,link_list->link_to,level);
link_list = link_list->next;
}
return;
}
static void node_print(GRAPH *g,GRAPH_NODE *node,int level)
{
if(!node)return;
level_print(level);
printf("node %s --->:\n",node->key.name);
link_list_print(g,node->link_list,level);
return;
}
void graph_route_print(GRAPH_ROUTE *route)
{
while(route)
{
printf("node %s --->:\n",route->node->key.name);
route = route->next;
}
printf("route print over\n");
}
void graph_print(GRAPH *g)
{
GRAPH_ROUTE_LIST *route_list;
assert(g);
route_list = g->route_list_head;
while(route_list)
{
printf("route list:%x cost=%d\n",route_list,route_list->cost);
graph_route_print(route_list->route_head);
route_list = route_list->next;
}
return;
}
GRAPH* graph_init(int node_dsize,int link_dsize,LINK_INFO_PRINT_FUNC func,LINK_KEY_CALC_FUNC lk_func)
{
GRAPH *g = malloc(sizeof(*g));
memset(g,0,sizeof(*g));
g->node_dsize = node_dsize;
g->link_dsize = link_dsize;
g->link_print_func = func;
g->link_key_func = lk_func;
g->root = NULL;
return g;
}
GRAPH_NODE* graph_node_init(NODE_KEY key,void *pdata,int dsize)
{
GRAPH_NODE *node = malloc(sizeof(*node));
memset(node,0,sizeof(*node));
node->pdata = malloc(sizeof(dsize));
node->key = key;
memcpy(node->pdata,pdata,dsize);
return node;
}
RV graph_add_root(GRAPH *g,GRAPH_NODE *node)
{
if(g->root)
{
printf("root is existed\n");
return R_EXISTED;
}
g->root = node;
return R_OK;
}
RV graph_node_linkto(GRAPH_NODE *from,GRAPH_NODE *to,void *pdata,int dsize)
{
GRAPH_LINK *link = malloc(sizeof(*link));
link->pdata = malloc(sizeof(dsize));
link->link_to = to;
memcpy(link->pdata,pdata,dsize);
link->next = from->link_list;
from->link_list = link;
return R_OK;
}
static GRAPH_ROUTE_LIST* graph_new_route_list(GRAPH *g)
{
GRAPH_ROUTE_LIST *route_list = malloc(sizeof(*route_list));
memset(route_list,0,sizeof(*route_list));
route_list->next = g->route_list_head;
g->route_list_head = route_list;
return route_list;
}
static void link_list_traverse(GRAPH *g,GRAPH_ROUTE_LIST *route_list,GRAPH_LINK *link_list)
{
GRAPH_ROUTE *route = route_list->route_head;
GRAPH_ROUTE_LIST *new_route_list = route_list;
int cost = route_list->cost;
while(link_list)
{
if(!route->link)
route->link = link_list;
else // new route list
{
new_route_list = graph_new_route_list(g);
new_route_list->route_head = malloc(sizeof(GRAPH_ROUTE));
memcpy(new_route_list->route_head,route,sizeof(*route));
new_route_list->cost = cost;
route = new_route_list->route_head;
route->link = link_list;
}
new_route_list->cost += g->link_key_func(link_list->pdata);
node_traverse(g,new_route_list,link_list->link_to);
link_list = link_list->next;
}
return;
}
static void node_traverse(GRAPH *g,GRAPH_ROUTE_LIST *route_list,GRAPH_NODE *node)
{
if(!node)return;
GRAPH_ROUTE *new_route = malloc(sizeof(*new_route));
new_route->node = node;
new_route->next = route_list->route_head;
route_list->route_head = new_route;
link_list_traverse(g,route_list,node->link_list);
return;
}
void graph_traverse(GRAPH *g)
{
GRAPH_ROUTE_LIST *route_list = graph_new_route_list(g);
node_traverse(g,route_list,g->root);
return;
}
測試代碼:
/*最短 路徑問題 MSP */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "define.h"
#include "graph.h"
typedef enum{
PATH_WALK,
PATH_BUS,
}ePATH_TYPE;
typedef struct _LINK_INFO
{
ePATH_TYPE type;
int time_cost; //minutes
int bus_id;
}LINK_INFO;
typedef struct _node_info
{
/*TBD */
}NODE_INFO;
void graph_MSP_linkinfo_print(void *link_info)
{
LINK_INFO *info = (LINK_INFO *)link_info;
printf("PATH T=%d,C=%d\n",info->type,info->time_cost);
return;
}
int graph_MSP_linkkey_calc(void *link_info)
{
LINK_INFO *info = (LINK_INFO*)link_info;
return info->time_cost;
}
void graph_MSP(void)
{
GRAPH_NODE *R,*R1,*R2,*R12,*R21,*R22,*R123;
LINK_INFO link_info;
NODE_INFO node_info;
NODE_KEY key;
GRAPH *g = graph_init(sizeof(NODE_INFO),sizeof(LINK_INFO),graph_MSP_linkinfo_print,graph_MSP_linkkey_calc);
key.name = "R";
R = graph_node_init(key,&node_info,sizeof(node_info));
graph_add_root(g,R);
key.name = "R1";
R1 = graph_node_init(key,&node_info,sizeof(node_info));
key.name = "R2";
R2 = graph_node_init(key,&node_info,sizeof(node_info));
key.name = "R12";
R12 = graph_node_init(key,&node_info,sizeof(node_info));
key.name = "R21";
R21 = graph_node_init(key,&node_info,sizeof(node_info));
key.name = "R22";
R22 = graph_node_init(key,&node_info,sizeof(node_info));
key.name = "R123";
R123 = graph_node_init(key,&node_info,sizeof(node_info));
link_info.type = PATH_WALK;
link_info.time_cost = 5;
graph_node_linkto(R,R1,&link_info,sizeof(link_info));
link_info.type = PATH_WALK;
link_info.time_cost = 6;
graph_node_linkto(R,R2,&link_info,sizeof(link_info));
//R1-->R12
link_info.type = PATH_BUS;
link_info.time_cost = 3;
link_info.bus_id = 44;
graph_node_linkto(R1,R12,&link_info,sizeof(link_info));
//R2-->R21
link_info.type = PATH_BUS;
link_info.time_cost = 4;
link_info.bus_id = 33;
graph_node_linkto(R2,R21,&link_info,sizeof(link_info));
//R21-->R12
link_info.type = PATH_BUS;
link_info.time_cost = 5;
link_info.bus_id = 50;
graph_node_linkto(R21,R12,&link_info,sizeof(link_info));
//R2-->R22
link_info.type = PATH_BUS;
link_info.time_cost = 6;
link_info.bus_id = 33;
graph_node_linkto(R2,R22,&link_info,sizeof(link_info));
//R22-->R12
link_info.type = PATH_BUS;
link_info.time_cost = 2;
link_info.bus_id = 38;
graph_node_linkto(R22,R12,&link_info,sizeof(link_info));
//R12-->R123
link_info.type = PATH_BUS;
link_info.time_cost = 4;
link_info.bus_id = 28;
graph_node_linkto(R12,R123,&link_info,sizeof(link_info));
graph_traverse(g);
graph_print(g);
return;
}