Добавил:
YunonaKuzmicheva
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:КУРСОВАЯ код
.txt#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
const int MAX_VERTICES = 50;
struct Node {
int vertex;
int weight;
Node* next;
};
//ребро
struct Edge {
int v1, v2; //вершины
int weight; //длина пути
};
//граф
struct Graph {
int V, E; //кол-во вершин и ребер
Edge edges[50]; //массив ребер
};
//алгоритм Крускала
// Функция для поиска корня поддерева
// Для каждой вершины графа создается массив связанных с ней ребер,
// где каждое ребро представляется структурой Node.
// При поиске корня поддерева мы идем по связанным с вершиной ребрам до тех пор,
// пока не найдем вершину, у которой нет родителя (parent[i] == -1).
// Это и будет корень поддерева.
int findParent(int parent[], int i) {
if (parent[i] == -1) {
return i;
}
return findParent(parent, parent[i]);
}
//Функция для объединения двух подмножеств
// При объединении подмножеств мы находим корни каждого подмножества,
// сравниваем их ранги и присоединяем одно подмножество к другому.
void unionSets(int parent[], int rank[], int x, int y) {
int xroot = findParent(parent, x);
int yroot = findParent(parent, y);
if (rank[xroot] < rank[yroot]) {
parent[xroot] = yroot;
else if (rank[xroot] > rank[yroot]) {
parent[yroot] = xroot;
else {
parent[yroot] = xroot;
rank[xroot]++;
}
// Функция для построения минимального остовного дерева алгоритмом Крускала
// Вначале создаем массив родителей для каждой вершины и инициализируем его значением -1,
// что означает, что у каждой вершины нет родителя.
// Также создаем массив рангов для каждой вершины и инициализируем его значением 0.
// Затем сортируем массив ребер по возрастанию весов.
// Далее проходим по отсортированному массиву ребер и добавляем их в остовное дерево,
// если они не образуют цикл с уже добавленными ребрами.
//Алгортм Крускала
void Graph kruskalMST(Graph graph) {
Graph MST;
MST.V = graph.V;
MST.E = 0;
int parent[graph.V];
int rank[graph.V];
for (int i = 0; i < graph.V; i++) {
parent[i] = -1;
rank[i] = 0;
}
Edge edges[graph.E];
for (int i = 0; i < graph.E; i++) {
edges[i] = graph.edges[i];
}
std::sort(edges, edges + graph.E, [](Edge a, Edge b) {
return a.weight < b.weight;
);
for (int i = 0; i < graph.E; i++) {
int x = findParent(parent, edges[i].v1);
int y = findParent(parent, edges[i].v2);
if (x != y) {
MST.edges[MST.E++] = edges[i];
unionSets(parent, rank, x, y);
}
}
return MST;
}
//чтение матрицы смежности из файла
int readMatrix(const string& filename, int matrix[50][50], char graph[50]) {
int size = 0;
string s;
ifstream file(filename);
if (file.is_open()) {
getline(file, s);
//чтение графов
for (int i = 0; i < s.length(); i++) {
if (s[i] != ' ') {
graph[size] = s[i];
size++;
}
}
//чтение матрицы смежности
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
file >> matrix[i][j];
if (matrix[i][j] < 0) {
return 0;
}
}
}
file.close();
}
else {
cout << "Ошибка открытия файла!" << std::endl;
}
return size;
}
//проверка матрицы
int isCorrectMatrix(int matrix[50][50], int ver)
{
int edge = 0;
//проверяем, что все элементы на главной диагонали равны нулю
for (int i = 0; i < ver; i++) {
if (matrix[i][i] != 0) {
return 0;
}
}
//проверяем, что матрица симметрична относительно главной диагонали
for (int i = 0; i < ver; i++) {
for (int j = i + 1; j < ver; j++) {
if (matrix[i][j] != matrix[j][i]) {
return 0;
}
else if (matrix[i][j] != 0) {
edge++;
}
}
}
return edge;
}
//Создание списка смежности
void createAdjacencyList(Graph* graph, char vertex[50], Node* adjList[50]) {
for (int i = 0; i < graph->V; i++) {
adjList[i] = nullptr;
}
for (int i = 0; i < graph->E; i++) {
int v1 = graph->edges[i].v1;
int v2 = graph->edges[i].v2;
int weight = graph->edges[i].weight;
Node* newNode = new Node;
newNode->vertex = v2;
newNode->weight = weight;
newNode->next = adjList[v1];
adjList[v1] = newNode;
newNode = new Node;
newNode->vertex = v1;
newNode->weight = weight;
newNode->next = adjList[v2];
adjList[v2] = newNode;
}
// Вывод списка смежности
cout << "Список смежности:" << endl;
for (int i = 0; i < graph->V; i++) {
cout << vertex[i] << " -> ";
Node* current = adjList[i];
while (current != nullptr) {
cout << vertex[current->vertex] << "(" << current->weight << ") ";
current = current->next;
}
cout << endl;
}
}
// Функция для создания матрицы инцидентности
void createIncidenceMatrix(Graph graph) {
int incidenceMatrix[graph.V][graph.E];
// Инициализируем матрицу инцидентности нулями
for (int i = 0; i < graph.V; i++) {
for (int j = 0; j < graph.E; j++) {
incidenceMatrix[i][j] = 0;
}
}
// Заполняем матрицу инцидентности единицами и минус единицами
for (int i = 0; i < graph.E; i++) {
incidenceMatrix[graph.edges[i].v1][i] = 1;
incidenceMatrix[graph.edges[i].v2][i] = -1;
}
// Выводим матрицу инцидентности на экран
for (int i = 0; i < graph.V; i++) {
for (int j = 0; j < graph.E; j++) {
std::cout << incidenceMatrix[i][j] << " ";
}
std::cout << std::endl;
}
// Функция для обхода в глубину
void DFS(int vertex, bool visited[], Node* adjacencyList[]) {
visited[vertex] = true;
std::cout << vertex << " ";
Node* currentNode = adjacencyList[vertex];
while (currentNode != nullptr) {
int adjacentVertex = currentNode->vertex;
if (!visited[adjacentVertex]) {
DFS(adjacentVertex, visited, adjacencyList);
}
currentNode = currentNode->next;
}
// Функция для обхода в глубину всего графа
void depthFirstTraversal(Graph graph) {
bool visited[graph.V];
for (int i = 0; i < graph.V; i++) {
visited[i] = false;
}
Node* adjacencyList[graph.V];
for (int i = 0; i < graph.V; i++) {
adjacencyList[i] = nullptr;
}
// Создаем список смежности
for (int i = 0; i < graph.E; i++) {
int v1 = graph.edges[i].v1;
int v2 = graph.edges[i].v2;
// Добавляем ребро в список смежности первой вершины
Node* newNode1 = new Node;
newNode1->vertex = v2;
newNode1->weight = graph.edges[i].weight;
newNode1->next = adjacencyList[v1];
adjacencyList[v1] = newNode1;
// Добавляем ребро в список смежности второй вершины
Node* newNode2 = new Node;
newNode2->vertex = v1;
newNode2->weight = graph.edges[i].weight;
newNode2->next = adjacencyList[v2];
adjacencyList[v2] = newNode2;
}
// Обходим все вершины графа в глубину
for (int i = 0; i < graph.V; i++) {
if (!visited[i]) {
DFS(i, visited, adjacencyList);
}
}
// Функция для обхода в ширину
void breadthFirstTraversal(Graph graph, int startVertex) {
bool visited[graph.V];
for (int i = 0; i < graph.V; i++) {
visited[i] = false;
}
Node* adjacencyList[graph.V];
for (int i = 0; i < graph.V; i++) {
adjacencyList[i] = nullptr;
}
// Создаем список смежности
for (int i = 0; i < graph.E; i++) {
int v1 = graph.edges[i].v1;
int v2 = graph.edges[i].v2;
// Добавляем ребро в список смежности первой вершины
Node* newNode1 = new Node;
newNode1->vertex = v2;
newNode1->weight = graph.edges[i].weight;
newNode1->next = adjacencyList[v1];
adjacencyList[v1] = newNode1;
// Добавляем ребро в список смежности второй вершины
Node* newNode2 = new Node;
newNode2->vertex = v1;
newNode2->weight = graph.edges[i].weight;
newNode2->next = adjacencyList[v2];
adjacencyList[v2] = newNode2;
}
// Очередь для обхода в ширину
std::queue<int> q;
visited[startVertex] = true;
q.push(startVertex);
while (!q.empty()) {
int currentVertex = q.front();
q.pop();
std::cout << currentVertex << " ";
Node* currentNode = adjacencyList[currentVertex];
while (currentNode != nullptr) {
int adjacentVertex = currentNode->vertex;
if (!visited[adjacentVertex]) {
visited[adjacentVertex] = true;
q.push(adjacentVertex);
}
currentNode = currentNode->next;
}
}
void printSeparator() {
cout << setfill('-') << setw(50) << "-" << setfill(' ') << endl;
}
void displayMenu() {
printSeparator();
cout << "Меню:" << endl;
cout << "1. Выполнить обход графа" << endl;
cout << "2. Вывести список смежности" << endl;
cout << "3. Вывести матрицу инцидентности" << endl;
cout << "4. Выйти из программы" << endl;
printSeparator();
}
void performTraversal(Graph* graph, char vertex[], Node* adjList[], bool isDFS) {
int n = -1;
cout << "С какой вершины провести обход?" << endl;
while (n < 0) {
char w;
cin >> w;
for (int i = 0; i < graph->V; i++) {
if (w == vertex[i]) {
n = i;
break;
}
}
if (n == -1) {
cout << "Неверное значение" << endl;
}
}
cout << endl;
DFS(graph, n, vertex, adjList);
BFS(graph, n, vertex, adjList);
cout << endl;
}
void printAdjacencyMatrix(Graph* graph, char vertex[50], int adjacencyMatrix[MAX_VERTICES][MAX_VERTICES]) {
cout << "Матрица смежности:" << endl;
printSeparator();
for (int i = 0; i < graph->V; i++) {
for (int j = 0; j < graph->V; j++) {
cout << setw(2) << adjacencyMatrix[i][j] << " ";
}
cout << endl;
}
printSeparator();
}
int main() {
setlocale(LC_ALL, "rus");
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
Graph graph;
string filename = "graph.txt";
int matrix[50][50];
char vertex[50];
int edge = 0, ver = 0;
ver = readMatrix(filename, matrix, vertex);
edge = isCorrectMatrix(matrix, ver);
if (!ver || !edge) {
cout << "Неверная запись в файле" << endl;
}
else {
cout << "Матрица смежности:" << endl;
printSeparator();
for (int i = 0; i < ver; i++) {
cout << vertex[i] << " ";
}
cout << endl;
for (int i = 0; i < ver; i++) {
for (int j = 0; j < ver; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
printSeparator();
graph.V = ver;
graph.E = edge;
int q = 0;
for (int i = 0; i < ver; i++) {
for (int j = i + 1; j < ver; j++) {
if (matrix[i][j] != 0) {
graph.edges[q].v1 = i;
graph.edges[q].v2 = j;
graph.edges[q].weight = matrix[i][j];
q++;
}
}
}
cout << endl;
Kruskal(&graph, vertex);
Node* adjList[50];
int incidenceMatrix[MAX_VERTICES][MAX_VERTICES];
while (true) {
displayMenu();
int choice;
cout << "Выберите действие (1-4): ";
cin >> choice;
switch (choice) {
case 1:
performTraversal(&graph, vertex, adjList, true); // true для DFS
break;
case 2:
createAdjacencyList(&graph, vertex, adjList);
break;
case 3:
createIncidenceMatrix(&graph, vertex, incidenceMatrix);
break;
case 4:
cout << "Программа завершена." << endl;
return 0;
default:
cout << "Неверный выбор. Попробуйте еще раз." << endl;
}
}
}
return 0;
}
Соседние файлы в предмете Алгоритмы и системы данных
