Загрузка данных
Отлично! Теперь перед нами полный текст методического материала со всеми подсказками и рекомендуемыми структурами данных.
Опираясь на этот справочный материал, я обновил и максимально адаптировал решения некоторых заданий, чтобы они строго соответствовали требованиям преподавателя (например, считывание одномерного массива поэлементно, использование TryGetValue в словаре и правильный вывод матриц/строк через предложенные вам конструкции).
Вот эталонные решения для всех 8 заданий вашей лабораторной работы.
Задание 1: Инвертирование одномерного массива
Используется построчное считывание размера, заполнение в цикле и классический алгоритм разворота через temp.
csharp
using System;
class Program
{
static void Main()
{
// 1. Считывание массива чисел из консоли (по методичке)
Console.WriteLine("Введите количество элементов массива:");
int n = int.Parse(Console.ReadLine());
int[] m = new int[n];
for (int i = 0; i < n; i++)
{
Console.WriteLine("Введите элемент {0}:", i + 1);
m[i] = int.Parse(Console.ReadLine());
}
// Вывод исходного массива на экран перед изменением
Console.Write("Исходный массив: ");
for (int i = 0; i < m.Length; i++)
{
Console.Write("{0} ", m[i]);
}
Console.WriteLine();
// 2. Алгоритм инвертирования (разворота) массива
int temp;
for (int i = 0; i < m.Length / 2; i++)
{
temp = m[i]; // временно сохраняем значение с начала
m[i] = m[m.Length - 1 - i]; // записываем значение с конца
m[m.Length - 1 - i] = temp; // записываем сохраненное значение
}
// Вывод инвертированного массива
Console.Write("Инвертированный массив: ");
for (int i = 0; i < m.Length; i++)
{
Console.Write("{0} ", m[i]);
}
Console.WriteLine();
}
}
Используйте код с осторожностью.
Задание 2: Заполнение двумерного массива «змейкой»
Размерность М и N задана в коде, заполнение от 1 до M*N с помощью условий if/else для управления направлением.
csharp
using System;
class Program
{
static void Main()
{
int rows = 3; // Переменная M из условия
int cols = 3; // Переменная N из условия
int[,] matrix = new int[rows, cols];
int currentNumber = 1;
for (int i = 0; i < rows; i++)
{
// if, else используются для управления направлением движения змейки
if (i % 2 == 0)
{
// Четная строка: идем слева направо (от 0 до cols - 1)
for (int j = 0; j < cols; j++)
{
matrix[i, j] = currentNumber++;
}
}
else
{
// Нечетная строка: змейка разворачивается справа налево (от cols - 1 до 0)
for (int j = cols - 1; j >= 0; j--)
{
matrix[i, j] = currentNumber++;
}
}
}
// Вывод матрицы в консоль (по методичке)
Console.WriteLine("Матрица:");
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
Console.Write(matrix[i, j] + " ");
}
Console.WriteLine();
}
}
}
Используйте код с осторожностью.
Задание 3: Копирование одномерного массива в двумерный построчно
Элементы одномерного массива последовательно переносятся в матрицу размерностью MxN.
csharp
using System;
class Program
{
static void Main()
{
int rows = 3;
int cols = 3;
// Входной одномерный массив размерностью M*N (задан в коде)
int[] sourceArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[,] matrix = new int[rows, cols];
// Построчное копирование с использованием дополнительного индекса
int sourceIndex = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
matrix[i, j] = sourceArray[sourceIndex++];
}
}
// Вывод одномерного массива
Console.Write("Исходный одномерный массив: ");
for (int i = 0; i < sourceArray.Length; i++)
{
Console.Write("{0} ", sourceArray[i]);
}
Console.WriteLine("\n");
// Вывод полученной матрицы в консоль
Console.WriteLine("Двумерный массив (матрица):");
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
Console.Write(matrix[i, j] + " ");
}
Console.WriteLine();
}
}
}
Используйте код с осторожностью.
Задание 4: Поиск минимального и максимального элементов
Заполнение матрицы случайными числами через класс Random и поиск экстремумов.
csharp
using System;
class Program
{
static void Main()
{
int rows = 3;
int cols = 3;
int[,] matrix = new int[rows, cols];
// Используем класс Random для заполнения
Random rnd = new Random();
Console.WriteLine("Сгенерированная матрица:");
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
matrix[i, j] = rnd.Next(1, 100); // случайные числа от 1 до 99
Console.Write(matrix[i, j] + " ");
}
Console.WriteLine();
}
// Алгоритм поиска MAX и MIN
int min = matrix[0, 0];
int max = matrix[0, 0];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (matrix[i, j] < min) min = matrix[i, j];
if (matrix[i, j] > max) max = matrix[i, j];
}
}
Console.WriteLine($"\nВыход: MIN = {min}, MAX = {max}");
}
}
Используйте код с осторожностью.
Задание 5: Подсчет количества разных символов в строке
Используется цикл foreach для перебора символов введенной строки и коллекция для определения уникальности.
csharp
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
Console.WriteLine("Введите строку символов:");
string str = Console.ReadLine();
// Коллекция HashSet хранит только уникальные элементы
HashSet<char> uniqueChars = new HashSet<char>();
// Цикл foreach используется для итерации по символам в строке
foreach (char c in str)
{
uniqueChars.Add(c);
}
Console.WriteLine($"Вход: \"{str}\"");
Console.WriteLine($"Выход: Symbols = {uniqueChars.Count};");
}
}
Используйте код с осторожностью.
Задание 6: Подсчет повторений для каждого символа
Используется строго указанный в методичке компактный подход с методом TryGetValue.
csharp
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
Console.WriteLine("Введите строку символов:");
string str = Console.ReadLine();
// Объявление словаря, где ключ — символ (char), а значение — число повторений (int)
Dictionary<char, int> counts = new Dictionary<char, int>();
// Перебор символов в верхнем регистре (чтобы 'м' и 'М' считались одинаково, как в примере)
foreach (char c in str)
{
char upperC = char.ToUpper(c);
// Пытаемся получить текущее значение по ключу upperC через TryGetValue
if (counts.TryGetValue(upperC, out int value))
{
counts[upperC] = value + 1; // если ключ найден — увеличиваем значение
}
else
{
counts[upperC] = 1; // если ключа не было — заводим новый со значением 1
}
}
Console.WriteLine($"Вход: \"{str}\"");
Console.Write("Выход: ");
// Перебор всех пар «ключ — значение» словаря через KeyValuePair
bool first = true;
foreach (KeyValuePair<char, int> pair in counts)
{
if (pair.Key == ' ') continue; // Пропускаем пробелы, если нужно как в примере
if (!first) Console.Write(", ");
Console.Write("{0} = {1}", pair.Key, pair.Value);
first = false;
}
Console.WriteLine(";");
}
}
Используйте код с осторожностью.
Задание 7: Удаление символа из строки без готовых функций
Алгоритм построения новой строки через фильтрацию символов в цикле (на основе примера из методички).
csharp
using System;
class Program
{
static void Main()
{
Console.WriteLine("Введите исходную строку:");
string str = Console.ReadLine();
Console.WriteLine("Введите символ для удаления:");
char target = Console.ReadKey().KeyChar;
Console.WriteLine(); // перевод строки после ввода символа
string result = ""; // результирующая пустая строка
// Реализация алгоритма из методички
for (int i = 0; i < str.Length; i++)
{
if (str[i] != target) // если текущий символ не совпадает с удаляемым
{
result += str[i]; // копируем его в результирующую строку
}
}
Console.WriteLine($"Вход: \"{str}\", \"{target}\"");
Console.WriteLine($"Выход: \"{result}\"");
}
}
Используйте код с осторожностью.
Задание 8: Замер времени обхода матрицы (Строки против Столбцов)
Используется класс Stopwatch для замера двух изолированных проходов по одной матрице.
csharp
using System;
using System.Diagnostics; // Необходимо для Stopwatch
class Program
{
static void Main()
{
int N = 4000; // Выбрано число в диапазоне 2500 - 10000
int[,] matrix = new int[N, N];
long dummySum = 0; // Переменная для исключения оптимизаций компилятора
Stopwatch sw = new Stopwatch();
// --- Тест 1: Обход по СТРОКАМ (внешний i, внутренний j) ---
sw.Start();
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
dummySum += matrix[i, j];
}
}
sw.Stop();
long rowTime = sw.ElapsedMilliseconds;
Console.WriteLine("Время выполнения (по строкам): {0} мс", rowTime);
// Сброс счетчика времени перед вторым тестом
sw.Reset();
dummySum = 0;
// --- Тест 2: Обход по СТОЛБЦАМ (внешний j, внутренний i) ---
sw.Start();
for (int j = 0; j < N; j++)
{
for (int i = 0; i < N; i++)
{
dummySum += matrix[i, j];
}
}
sw.Stop();
long colTime = sw.ElapsedMilliseconds;
Console.WriteLine("Время выполнения (по столбцам): {0} мс", colTime);
}
}
Используйте код с осторожностью.
Ответы на контрольные вопросы:
1. Какой вариант цикла быстрее проходит по всему циклу?
Обход по строкам выполняется значительно быстрее. В языке C# двумерные массивы ([,]) хранятся в оперативной памяти последовательно — строка за строкой. Когда мы идем по строкам, процессор считывает данные из соседних ячеек памяти подряд и эффективно использует кэш-память процессора (кэш-линии). При обходе по столбцам происходят «прыжки» в памяти через целые строки, из-за чего возникают промахи кэша (cache misses) и процессору приходится постоянно ждать подгрузки данных из медленной оперативной памяти.
2. Меняется ли общее количество итераций цикла?
Нет, общее количество итераций не меняется. В обоих случаях внутреннее тело цикла выполняется ровно \(N \times N\) раз (например, при \(N = 4000\) это ровно \(16\,000\,000\) операций). Разница во времени обусловлена только тем, в каком порядке эти ячейки запрашиваются из оперативной памяти.
Если у вас возникнут вопросы по работе с Visual Studio или по запуску кода, дайте знать — я помогу!