linux kernel data struct: dijkstra算法

今天来看看这个算法,鸣谢一位同事给讲解这个算法,算法的思想大家可以去了解一下;

算法主要思想:找出图中任意一点出发,找出到其他点的最短路径;

实现上往往会有一个集合来存放已知点,每次加入一个点;加入的方法是:找出集合点的所有路径,筛选出离A点最近的点,加到集合中。

这里简单的对其实现:

 

 

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

#define N 5   //5个点

typedef enum {
  OK,
  ERR_OPEN,
  ERR_DATA_INPUT     
} ERR_NO;

typedef struct cell {
       int value;
       char is_path_used;
} CELL;

typedef struct map {
    char index[N];   //not used..
    CELL a[N][N];
}MAP;

static MAP map;

typedef enum{
    STATION_A,
    STATION_B,
    STATION_C,
    STATION_D,
    STATION_E
}STATION;

typedef struct {
   int count;
   int value;
   STATION a[N];  
}NEAREST_PATH;

//已知路径集合
struct s{
    int count;
    STATION know_set[N];
}know_station_set;

//对应图中的 弧  <v1,v2>
typedef struct v {
    int v1_2_v2_value;
    int A_2_v2_value;
    STATION v1;
    STATION v2;
}V_STATION;

//最小路径:  Path_A_2_X[0] 表示 A->A
//Path_A_2_X[1] 表示 A->B
//etc.
static NEAREST_PATH Path_A_2_X[5];

int read_data_from_file(void)
{
  int i, j;
  FILE *fp;

  printf("*****************\n");
 
  if((fp = fopen("test.txt", "rt")) == NULL)
  {
      printf("cannot open file\n");
      return -1;
  }
 
  for(i = 0; i < N; i++)
  {
        for(j = 0; j < N; j++)
        {
              fscanf(fp, "%d", &map.a[i][j].value);
        }    
  }
  printf("read data as:\n");
 
  for(i = 0; i < N; i++)
  {
        for(j = 0; j < N; j++)
        {
              printf("%5d",map.a[i][j].value);
        }    
        printf("\n");
  } 
 
  for(i = 0; i < N; i++)
  {
        for(j = 0; j < N; j++)
        {
             if(map.a[i][j].value != map.a[j][i].value) return -ERR_DATA_INPUT;
        }  
  }

  return 0;
}

char * get_station_name(STATION x)
{
     switch(x)
     {
         case STATION_A: return "A";
         case STATION_B: return "B";
         case STATION_C: return "C";
         case STATION_D: return "D";
         case STATION_E: return "E";
        
         default : return "No name";
     }
}

int is_station_in_knowset(STATION x)
{
    int i;
   
    for(i = 0; i < know_station_set.count; i++)
    {
         if(x == know_station_set.know_set[i]) return 1;
    }
   
    return 0;
}

STATION nearest_station(STATION x)
{
    int j;
    int min_value = 100, min_num = 0;
   
    for(j = 0; j < N; j++)
    {
        //printf("j = %d, map.a[%d][%d].value = %d\n", j, x, j, map.a[(int)x][j].value);
        //走过的点路径要滤掉
        if(map.a[(int)x][j].value != 0 && min_value > map.a[(int)x][j].value
           && !map.a[x][j].is_path_used)
        {
            //printf("****min_num = %d\n", j);
            //集合中已有的点也要滤掉
            if(is_station_in_knowset(j)) continue;
            min_num = j;
            min_value = map.a[(int)x][j].value;
        }
       
        //printf("*\n");
    }
   
    //printf("min_num = %5d\n", min_num);
    printf("%s station's nearest station is: %s\n", get_station_name(x), get_station_name((STATION)min_num));
    return (STATION)min_num;
}

void print_path_use_map(void)
{
    int i, j;

   printf("used path:\n");
   for(i = 0; i < N; i++)
   {
       for(j = 0; j < N; j++)
       {
           printf("%5d", map.a[i][j].is_path_used);     
       }
       printf("\n");
   }     
}

int A_2_knowset_V1_value(STATION v1)
{
    return Path_A_2_X[(int)v1].value;
}

//v1 is pre station, x is station now adding
void add_station_2_knowset(STATION x, STATION v1)
{
   int i;
  
   know_station_set.know_set[know_station_set.count] = x;
   know_station_set.count += 1;
  
   printf("adding station %s\n pre station is %s\n",
                        get_station_name(x), get_station_name(v1));
        
   printf("the know station set are:\n");              
   for(i = 0; i < know_station_set.count; i++)
   {
         printf(" %s ", get_station_name(know_station_set.know_set[i]));
   }
   printf("\n");
  
   if(v1 == STATION_A)
   {
       //printf("A->%s\n", get_station_name(x));
       Path_A_2_X[x].count = 2;
       Path_A_2_X[x].value = map.a[0][x].value;
       Path_A_2_X[x].a[1] = x;

   }
   else
   {
       printf("copy path: %d to %d\n", v1, x);
       //上一个点的最小路径是一样的
       memcpy(&Path_A_2_X[x],&Path_A_2_X[v1],sizeof(NEAREST_PATH));
      
       Path_A_2_X[x].a[Path_A_2_X[x].count] = x;
       Path_A_2_X[x].count += 1;
       Path_A_2_X[x].value += map.a[v1][x].value;
   }
}

void pick_station(void)
{
   int i, j;
   STATION n;
   STATION min_2_A;
   int min_value = 100;
   int min_pre_station = 0;
   int break_flag = 0;
  
   V_STATION a[5] = {0};
  
   print_path_use_map();
  
   for(i = 0; i < know_station_set.count; i++)
   {
       a[i].v1 = know_station_set.know_set[i];
       n = nearest_station(a[i].v1);   //找已知集合里每个点 最近的点,底下还要进行一次比较
       //if(n == -1) continue;
       a[i].v2 = n;
       //printf("%s", get_station_name(n));
       for(j = 0; j < know_station_set.count; j++)
       {
             if(n == know_station_set.know_set[j])
             {
                  break_flag = 1;
                  break;
             }
       }
      
       if(break_flag == 1)
       {
           break_flag = 0;
           continue;
       }
      
       //从A出发到备选点的最近距离
       a[i].v1_2_v2_value = map.a[a[i].v1][a[i].v2].value;
       a[i].A_2_v2_value = A_2_knowset_V1_value(a[i].v1) + a[i].v1_2_v2_value;
      
       //找出距离最小的点
       if(a[i].A_2_v2_value < min_value)
       {
           min_2_A = n;
           min_value = a[i].A_2_v2_value;
           min_pre_station = a[i].v1;
       }
   }
   
   //把最小的点添加到已知点集合中
   add_station_2_knowset(min_2_A, min_pre_station);

  //标记已知集合点所使用的路径,用于滤除备选点
  map.a[a[i].v1][min_2_A].is_path_used = 1;
  map.a[min_2_A][a[i].v1].is_path_used = 1;
  
  
}

void init_find_path(void)
{
   int i;
    
   know_station_set.know_set[know_station_set.count] = STATION_A;
   know_station_set.count += 1;
   
    Path_A_2_X[0].count = 1;
    Path_A_2_X[0].value = 0;
    Path_A_2_X[0].a[0] = STATION_A;
}

void print_near_path(void)
{
    int i, j;
   
    printf("\n*****print result******\n");
    for(i = 0; i < N; i++)
    {      
       printf("A->%s path is:\n", get_station_name(i));
       for(j = 0; j < Path_A_2_X[i].count; j++)
       {
             printf(" %s ", get_station_name(Path_A_2_X[i].a[j]));
       }   
       printf("\n the cost is: %d\n", Path_A_2_X[i].value);
       printf("---\n");
    }
}

int main(int argc, char *argv[])
{
  int res;
 
  res = read_data_from_file();
  if(res == -ERR_DATA_INPUT)
  {
       printf("err data input\n");
       system("PAUSE");
       return;
  }
  init_find_path();
 
  pick_station();
  pick_station();
  pick_station();
  pick_station();
 
  print_near_path();
 
  system("PAUSE"); 
  return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值