📊 Двумерни масиви и обработка на таблична информация
📊 Двумерни масиви
Двумерният масив е структура от данни, която позволява съхранение на стойности в табличен формат (редове и колони). Те често се използват за представяне на матрици, таблици, игрални полета и други подобни структури.
Деклариране и инициализация на двумерен масив в C++
В C++ двумерните масиви се декларират чрез два комплекта квадратни скоби:
Можем също да го инициализираме със стойности: Ако оставим C++ да определи броя на редовете:Достъп до елементи в двумерен масив
Достъпът до елементи става чрез индексите за ред и колона:
int x = matrix[1][2]; // Взима стойността от втория ред, трета колона
matrix[0][1] = 42; // Променя стойността на първи ред, втора колона
Въвеждане и извеждане на двумерен масив
#include <iostream>
using namespace std;
int main() {
const int rows = 2, cols = 3;
int matrix[rows][cols];
cout << "Въведете стойности за двумерния масив:" << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cin >> matrix[i][j];
}
}
cout << "Въведената матрица:" << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
return 0;
}
Обработка на таблична информация
Двумерните масиви са полезни за съхраняване и обработка на таблични данни като оценки, резултати, статистики и други.
Пример: Намиране на сумата на всички елементи:
int sum = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
sum += matrix[i][j];
}
}
cout << "Сумата на всички елементи е: " << sum << endl;
Пример: Намиране на максималния елемент:
int maxVal = matrix[0][0];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] > maxVal) {
maxVal = matrix[i][j];
}
}
}
cout << "Максималната стойност е: " << maxVal << endl;
🎮 Специални видове матрици
Квадратна матрица
Матрица с еднакъв брой редове и колони (N x N).
Главен и страничен диагонал
// Главен диагонал (елементи където i == j)
for (int i = 0; i < N; i++) {
cout << square[i][i] << " ";
}
// Страничен диагонал (елементи където i + j == N - 1)
for (int i = 0; i < N; i++) {
cout << square[i][N - 1 - i] << " ";
}
Транспониране на матрица
Размяна на редове и колони.
void transpose(int matrix[][100], int rows, int cols) {
int temp[100][100];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
temp[j][i] = matrix[i][j];
}
}
// Копиране обратно
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
matrix[i][j] = temp[i][j];
}
}
}
Матрично умножение
void multiply(int A[][100], int B[][100], int C[][100], int n, int m, int p) {
// A е n x m, B е m x p, C ще е n x p
for (int i = 0; i < n; i++) {
for (int j = 0; j < p; j++) {
C[i][j] = 0;
for (int k = 0; k < m; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
}
🗺️ Двумерни масиви в задачи с лабиринти и графи
Обхождане на съседи (4 посоки)
int dx[] = {-1, 1, 0, 0}; // Горе, долу, ляво, дясно
int dy[] = {0, 0, -1, 1};
for (int dir = 0; dir < 4; dir++) {
int newX = x + dx[dir];
int newY = y + dy[dir];
if (newX >= 0 && newX < rows && newY >= 0 && newY < cols) {
// Валидна позиция
}
}
Обхождане на съседи (8 посоки)
int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
for (int dir = 0; dir < 8; dir++) {
int newX = x + dx[dir];
int newY = y + dy[dir];
if (newX >= 0 && newX < rows && newY >= 0 && newY < cols) {
// Валидна позиция
}
}
Flood Fill алгоритъм
Запълване на област с нов цвят (подобно на инструмента "bucket fill" в графични редактори).
void floodFill(int grid[][100], int x, int y, int rows, int cols, int oldColor, int newColor) {
if (x < 0 || x >= rows || y < 0 || y >= cols) return;
if (grid[x][y] != oldColor) return;
grid[x][y] = newColor;
floodFill(grid, x-1, y, rows, cols, oldColor, newColor);
floodFill(grid, x+1, y, rows, cols, oldColor, newColor);
floodFill(grid, x, y-1, rows, cols, oldColor, newColor);
floodFill(grid, x, y+1, rows, cols, oldColor, newColor);
}
💾 Динамично алокиране на двумерни масиви
Използване на vector<vector<int>>
#include <vector>
using namespace std;
int main() {
int rows = 5, cols = 4;
vector<vector<int>> matrix(rows, vector<int>(cols, 0));
// Достъп до елементи
matrix[2][3] = 10;
// Обхождане
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
return 0;
}
📐 Префиксни суми в 2D
Префиксните суми в 2D позволяват бързо изчисляване на сумата на елементите в правоъгълна област.
void buildPrefix2D(int matrix[][100], int prefix[][101], int rows, int cols) {
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
prefix[i][j] = matrix[i-1][j-1] +
prefix[i-1][j] +
prefix[i][j-1] -
prefix[i-1][j-1];
}
}
}
int rangeSum2D(int prefix[][101], int r1, int c1, int r2, int c2) {
// Сума на правоъгълника от (r1, c1) до (r2, c2) включително
// Използваме 1-базирана индексация за prefix
return prefix[r2+1][c2+1] -
prefix[r1][c2+1] -
prefix[r2+1][c1] +
prefix[r1][c1];
}
🧱 Тип структура в C++. Масиви от структури.
🧱 Структури в C++
Структурите (struct) са потребителски дефинирани типове данни, които позволяват групиране на различни свързани стойности в една логическа единица.
Деклариране на структура
ТукStudent е структура, съдържаща три полета: име, възраст и оценка.
Създаване и използване на структури
Student s1 = {"Иван", 20, 5.50};
cout << "Име: " << s1.name << ", Възраст: " << s1.age << ", Оценка: " << s1.grade << endl;
Масиви от структури
Можем да създадем масив от структури за съхранение на множество обекти.
Въвеждане и извеждане на масив от структури
#include <iostream>
using namespace std;
struct Student {
string name;
int age;
double grade;
};
int main() {
const int size = 3;
Student students[size];
cout << "Въведете информация за студентите:" << endl;
for (int i = 0; i < size; i++) {
cout << "Име: ";
cin >> students[i].name;
cout << "Възраст: ";
cin >> students[i].age;
cout << "Оценка: ";
cin >> students[i].grade;
}
cout << "Списък на студентите:" << endl;
for (int i = 0; i < size; i++) {
cout << students[i].name << " - Възраст: " << students[i].age << ", Оценка: " << students[i].grade << endl;
}
return 0;
}
Търсене и обработка на данни в масив от структури
Пример: Намиране на студент с най-висока оценка:
Student bestStudent = students[0];
for (int i = 1; i < size; i++) {
if (students[i].grade > bestStudent.grade) {
bestStudent = students[i];
}
}
cout << "Студент с най-висока оценка: " << bestStudent.name << " (" << bestStudent.grade << ")" << endl;
Пример: Среден успех на групата:
double totalGrade = 0;
for (int i = 0; i < size; i++) {
totalGrade += students[i].grade;
}
double averageGrade = totalGrade / size;
cout << "Среден успех на групата: " << averageGrade << endl;
🎯 Сортиране на структури
Използване на sort с компаратор
#include <algorithm>
#include <vector>
bool compareByGrade(const Student& a, const Student& b) {
return a.grade > b.grade; // Низходящо по оценка
}
int main() {
vector<Student> students = {
{"Иван", 20, 5.50},
{"Мария", 21, 5.80},
{"Георги", 19, 4.90}
};
sort(students.begin(), students.end(), compareByGrade);
for (const auto& s : students) {
cout << s.name << ": " << s.grade << endl;
}
return 0;
}
Множествено сортиране
Сортиране по няколко критерия (първо по оценка, после по име).
bool compareMultiple(const Student& a, const Student& b) {
if (a.grade != b.grade) {
return a.grade > b.grade; // По-висока оценка първа
}
return a.name < b.name; // При равни оценки - по азбучен ред
}
📊 Задачи за практика
- Ротация на матрица: Завъртете квадратна матрица на 90 градуса по часовниковата стрелка.
- Спирала: Обходете матрица по спирала (от външните елементи към центъра).
- Седловина точка: Намерете елемент, който е минимален в реда си и максимален в колоната си.
- Zigzag обхождане: Обходете матрица в зигзаг ред.
- Остров: Броене на "острови" в двоична матрица (свързани единици).
- База данни студенти: Създайте програма за управление на студенти с търсене, сортиране и филтриране.
- Паскалов триъгълник: Генерирайте първите N реда на Паскаловия триъгълник в матрица.
🏁 Заключение
Разбирането на двумерните масиви и структурите в C++ е ключово за ефективната обработка на таблична информация и обекти от реалния свят. Двумерните масиви позволяват работа с големи количества данни в табличен формат, докато структурите предоставят удобен начин за групиране на свързана информация. Масивите от структури комбинират двете концепции, осигурявайки мощен инструмент за програмиране. Префиксните суми в 2D са важна оптимизация за задачи със запитвания върху правоъгълни области. Уверете се, че разбирате индексацията, границите и основните алгоритми за обхождане на двумерни масиви. 🚀