Advertisement
dmkozyrev

search_path

Jan 22nd, 2016
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.39 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. // Чтение графа происходит из файла in.txt, который устроен следующим образом
  4. // Сначала идут три целых числа: n - количество вершин, a - пункт отправления, b - пункт назначения
  5. // Затем идет n строк по n целых чисел в каждой строке - матрица смежности графа
  6. // Запись осуществляется в файл out.txt
  7.  
  8. unsigned const int MAX_SIZE = 100; // Максимальное количество вершин
  9.  
  10. void read_graph(int * graph, int * n, int * a, int * b, const char * filename); // Чтение входных данных
  11. int search_path(int * graph, int n, int a, int b, int * path, int * path_len); // Поиск пути
  12. void write_path(int * path, int n, const char * filename); // Запись выходных данных
  13.  
  14. int pop(int * queue, int * n); // Вынуть верхний элемент из очереди
  15. void push(int * queue, int * n, int value); // Добавить в конец очереди новый элемент
  16.  
  17. int main(){
  18.     int graph[MAX_SIZE][MAX_SIZE]; // Матрица смежности графа
  19.     int n, a, b; // n - количество вершин. Из вершины a в вершину b ищем минимальный путь
  20.     int path[MAX_SIZE]; // Путь
  21.     int path_len; // Его длина
  22.     int * ptr_graph = (int*)graph; // Указатель на матрицу смежности
  23.    
  24.     read_graph(ptr_graph, &n, &a, &b, "in.txt"); // Считываем граф
  25.    
  26.     if (search_path(ptr_graph, n, a, b, path, &path_len)) // Ищем путь
  27.         printf("The path has been successfully found!\n");
  28.     else
  29.         printf("The right path does not exist!\n");
  30.        
  31.     write_path(path, path_len, "out.txt"); // Записываем путь в файл
  32.    
  33.     return 0;
  34. }
  35.  
  36. void read_graph(int * graph, int * n, int * a, int * b, const char * filename){
  37. //  Открываем файл для чтения:   
  38.     FILE *fp;
  39.     fp = fopen(filename, "r");
  40.    
  41. //  Считываем оттуда количество вершин, вершину a и вершину b:
  42.     fscanf(fp, "%d %d %d", n, a, b);
  43.    
  44. //  Считываем оттуда матрицу смежности графа:
  45.     int i, j;
  46.     for (i = 0; i < *n; i++)
  47.         for (j = 0; j < *n; j++)
  48.             fscanf(fp, "%d ", graph+(*n)*i+j);
  49.            
  50. //  Закрываем файл
  51.     fclose(fp);
  52. }
  53.  
  54. int pop(int * queue, int * n){
  55. //  Вынимаем элемент из очереди
  56.     int t = queue[0], i;
  57.     *n -= 1;
  58.     for(i = 0; i < *n; i++)
  59.         queue[i] = queue[i+1];
  60.     return t;
  61. }
  62.  
  63. void push(int * queue, int * n, int value){
  64. //  Кладем новый элемент в очередь
  65.     queue[*n] = value;
  66.     *n += 1;
  67. }
  68.  
  69. int search_path(int * graph, int n, int a, int b, int * path, int * path_len){
  70. //  Ищем минимальный путь поиском в ширину
  71.     *path_len = 0; // Длина пути
  72.    
  73.     int visited[MAX_SIZE], q[MAX_SIZE]; // Посещенные вершины и очередь для посещения вершин
  74.     int q_len = 0, i, j; // Длина очереди и счетчики циклов
  75.    
  76.     for(i = 0; i < n; i++) // Обнуляем массив посещенных вершин
  77.         visited[i] = -1;
  78.            
  79. //  Кидаем стартовую вершину в очередь и запоминаем, что мы ее посетили:
  80.     push(q, &q_len, a);
  81.     visited[a] = a;
  82.    
  83. //  Пока мы не обработали необходимые вершины, обрабатываем их:
  84.     while (q_len > 0) {
  85. //      Вынимаем очередную вершину:
  86.         const int t = pop(q, &q_len);
  87. //      Если мы достигли необходимой вершины, то логично бы прекратить поиск
  88.         if (t == b) break;
  89. //      В цикле кидаем в очередь все посещенные смежные с вершиной t вершины:
  90.         for (i = 0; i < n; i++)
  91. //          ЕСЛИ существует ребро t -> i и ЕСЛИ мы по нему еще не прошли:
  92.             if (*(graph+t*n+i) && visited[i] == -1 ) {
  93.                 visited[i] = t; // Сохраняем в visited[i] вершину t, из которой мы пришли в вершину i
  94.                 push(q, &q_len, i); // Кидаем вершину i в очередь обработки
  95.             }      
  96.     }
  97.    
  98. //  Возвращаемся из вершины b в вершину a по тому пути , который мы запомнили в visited
  99.     while ( b != a && visited[b] != -1 ){
  100.         push(path, path_len, b); // Кидаем вершины в вектор пути
  101.         b = visited[b];
  102.     }
  103.  
  104. //  Если нам удалось дойти до стартовой вершины , то кидаем ее в наш путь
  105.     if ( b == a ) push(path, path_len, a);
  106.    
  107. //  Приведение пути к нормальному виду (переворачиваем его)
  108.     for (i = 0, j = *path_len-1; i < j; ++i,--j){
  109.         int temp = path[i];
  110.         path[i] = path[j];
  111.         path[j] = temp;
  112.     }  
  113.    
  114.     return *path_len; // Возвращаем длину найденного пути
  115. }
  116.  
  117. void write_path(int * path, int n, const char * filename){
  118. //  Запись пути в файл
  119.     FILE *fp;
  120.     fp = fopen(filename, "w");
  121.     int i;
  122.     for (i = 0; i < n; i++)
  123.         fprintf(fp, "%d ", path[i]);
  124. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement