From 2a7e9b411d4f7e270f971a5fc3b54fa8eb5a3e46 Mon Sep 17 00:00:00 2001 From: nihonium Date: Fri, 8 Apr 2022 13:57:34 +0300 Subject: [PATCH] fisrst algo --- algo/first/Makefile | 37 +++++++ algo/first/application_select.data | 8 -- algo/first/kruskal.c | 167 +++++++++++++++++++++++++++++ algo/first/kruskal.data | 6 ++ 4 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 algo/first/Makefile create mode 100644 algo/first/kruskal.c create mode 100644 algo/first/kruskal.data diff --git a/algo/first/Makefile b/algo/first/Makefile new file mode 100644 index 0000000..e04c2a7 --- /dev/null +++ b/algo/first/Makefile @@ -0,0 +1,37 @@ +CC=gcc +CFLAGS=-Wall -lm -Wall -Werror=sign-compare -Werror=array-bounds -Werror=maybe-uninitialized -Werror=unused-parameter -Werror=maybe-uninitialized -Werror=cast-qual + +EXECS=application_select warshall topological dijkstra prim kruskal + +build_application: application_select.c + $(CC) $(CFLAGS) application_select.c -o application_select +application_run: application_select + cat application_select.data | ./application_select + +build_warshall: warshall.c + $(CC) $(CFLAGS) warshall.c -o warshall +warshall_run: warshall + cat warshall.data | ./warshall + +build_topological: topological.c + $(CC) $(CFLAGS) topological.c -o topological +topological_run: topological + cat topological.data | ./topological + +build_dijkstra: dijkstra.c + $(CC) $(CFLAGS) dijkstra.c -o dijkstra +dijkstra_run: dijkstra + cat dijkstra.data | ./dijkstra + +build_prim: prim.c + $(CC) $(CFLAGS) prim.c -o prim +prim_run: prim + cat prim.data | ./prim + +build_kruskal: kruskal.c + $(CC) $(CFLAGS) kruskal.c -o kruskal +kruskal_run: kruskal + cat kruskal.data | ./kruskal + +clean: + rm -f $(EXECS) diff --git a/algo/first/application_select.data b/algo/first/application_select.data index 9d6f930..ba91432 100644 --- a/algo/first/application_select.data +++ b/algo/first/application_select.data @@ -1,5 +1,3 @@ -# 1 - 5 1 2 3 6 @@ -7,9 +5,3 @@ 5 7 1 7 -# 2 - -3 -1 5 -2 3 -3 4 diff --git a/algo/first/kruskal.c b/algo/first/kruskal.c new file mode 100644 index 0000000..be058dc --- /dev/null +++ b/algo/first/kruskal.c @@ -0,0 +1,167 @@ +#include +#include + +typedef struct edge { + int begin; + int end; + int len; +} Edge; + +int count_edge(int **adj, int n); +Edge* create_edge_vector(int **adj, int n, int size); +void print_edges(int** adj, int n); +int** solve(Edge* vector, int size, int size_vertex); +int vector_compare(const void *a, const void *b); +void paint_vertices(Edge* vector, int size, int need_vertix, int saved_color, int *paint); + +int main() { + /* n - количество вершин, size - количество ребер */ + + int n; + scanf("%d", &n); + int **adj = (int**)calloc(n, sizeof(int*)); + for (int i = 0; i < n; i++) { + adj[i] = (int*)calloc(n, sizeof(int)); + } + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + scanf("%d", &adj[i][j]); + } + } + /* Подсчет количества ребер в исходной матрице смежности */ + int size = count_edge(adj, n); + Edge *vector = create_edge_vector(adj, n, size); + /* Сортируем ребра по длине, сначала самые короткие */ + qsort(vector, size, sizeof(Edge), vector_compare); + + int **res = solve(vector, size, n); + print_edges(res, n); + + /* Освобождаем память */ + for (int i = 0; i < n; i++) { + free(adj[i]); + } + free(adj); + for (int i = 0; i < n; i++) { + free(res[i]); + } + free(res); + free(vector); +} + +int **solve(Edge* vector, int size, int v) { + /* Результирующее остовное дерево в виде матрицы смежности */ + int** res = (int**)calloc(v, sizeof(int*)); + for (int i = 0; i < v; i++) { + res[i] = (int*)calloc(v, sizeof(int)); + } + /* Массив с окраской каждой вершины */ + int* paint = (int*)calloc(v, sizeof(int)); + /* Количество рассмотренных вершин */ + int n = 0; + int color = 1; + int saved_color; + /* Пока не раскрашены все вершины */ + while (n != size ) { + /* Проверяем на цикл */ + if ((paint[vector[n].begin] == paint[vector[n].end]) && (paint[vector[n].begin] != 0 || paint[vector[n].end] != 0)) { + n++; + continue; + } + else { + /* Создание новой компоненты связности */ + if (paint[vector[n].begin] == 0 && paint[vector[n].end] == 0) {//обе вершины незакрашены + paint[vector[n].begin] = color; + paint[vector[n].end] = color; + res[vector[n].begin][vector[n].end] = vector[n].len; + /* Создаем новый цвет */ + color++; + } + /* Присоединение неокрашенной вершины к существующей компоненте связности */ + else if (paint[vector[n].begin] == 0) { + paint[vector[n].begin] = paint[vector[n].end]; + res[vector[n].begin][vector[n].end] = vector[n].len; + } + else if (paint[vector[n].end] == 0) { + paint[vector[n].end] = paint[vector[n].begin]; + res[vector[n].begin][vector[n].end] = vector[n].len; + } + /* Объединение компонент связности */ + else { + /* Сохраняем цвет той компоненты, которую будем перекрашивать */ + saved_color = paint[vector[n].end]; + paint[vector[n].end] = paint[vector[n].begin]; + res[vector[n].begin][vector[n].end] = vector[n].len; + /* Перекрашиваем вторую компоненту в цвет первой */ + paint_vertices(vector, size, vector[n].end, saved_color, paint); + } + n++; + } + } + free(paint); + return res; +} +void print_edges(int** massiv, int n) { + printf("Решение:\n"); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (massiv[i][j] != 0) { + printf("%d-%d: %d\n", i, j, massiv[i][j]); + } + } + } +} + +Edge* create_edge_vector(int **adj, int n, int size) { + Edge* vector = (Edge*)calloc(size, sizeof(Edge)); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (adj[i][j] != 0) { + /* Заполняем с конца */ + size--; + vector[size].begin = i; + vector[size].end = j; + vector[size].len = adj[i][j]; + } + } + } + return vector; +} + +int count_edge(int **adj, int n) { + int res = 0; + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (adj[i][j] != 0) { + res++; + } + } + } + return res; +} + +int vector_compare(const void *a, const void *b) { + return ((const Edge *)a)->len - ((const Edge *)b)->len; +} + +void paint_vertices(Edge* vector, int size, int need_vertix, int saved_color, int *paint) { + for (int i = 0; i < size; i++) { + /* Если текущая ребро выходит из нужной вершины */ + if (vector[i].begin == need_vertix) { + /* Если другой конец ребра - нужный по цвету (старый), то красим в цвет исходной вершины */ + if (paint[vector[i].end] == saved_color) { + paint[vector[i].end] = paint[need_vertix]; + /* Рекурсивно вызываем покраску для конца ребра */ + paint_vertices(vector, size, vector[i].end, saved_color, paint); + } + } + /* Если текущее ребро заканчивается в нужной вершине */ + else if (vector[i].end == need_vertix) { + /* Аналогично случаю выше, но вызываем для начала ребра */ + if (paint[vector[i].begin] == saved_color) { + paint[vector[i].begin] = paint[need_vertix]; + paint_vertices(vector, size, vector[i].begin, saved_color, paint); + } + } + } +} diff --git a/algo/first/kruskal.data b/algo/first/kruskal.data new file mode 100644 index 0000000..a1155bc --- /dev/null +++ b/algo/first/kruskal.data @@ -0,0 +1,6 @@ +5 +0 9 75 0 0 +9 0 95 19 42 +75 95 0 51 66 +0 19 51 0 31 +0 42 66 31 0