Лабораторная работа по C#. Работа с массивами

Задача: даны два массива a и b размерностью n и m соответственно, сформировать массив c таким образом, что первая часть — отсортированный по возрастанию массив а, а вторая часть — отсортированный по убыванию массив b.

Визуализация задачи

Прежде, чем приступим к написанию кода, представим, что должна будет выполнять наша программа. Итак, в задаче определено, что даны два одномерных массива, с некоторой размерностью, например, два массива целых чисел размерностью 5 и 3, соответственно:

int[] a = new int[5] { 2, 4, 5, 1, 4 };
int[] b = new int[3] { 9, 1, 4 };

далее, необходимо отсортировать первый массив по возрастанию, то есть получить вот такой массив a:

1, 2, 4, 4, 5

второй массив необходимо отсортировать по убыванию (от большего к меньшему), то есть, получить следующий массив:

9, 4, 1

и, на третьем шаге, мы должны объединить два массива в один, то есть получить вот такой массив чисел в качестве ответа:

1, 2, 4, 4, 5, 9, 4, 1

Разобравшись с тем, как должна работать наша программа, перейдем к следующему шагу — выявлению неопределенностей (неточностей) в формулировке самой задачи.

Неопределенности задачи

Первое: какой тип данных у массивов?

Теоретически, отсортировать в порядке возрастания и убывания можно всё, что угодно. Учитывая, что лабораторная работа выполняется, в основном, неподготовленными или слабо подготовленными людьми, примем, что массивы у нас будут содержать числа и, при этом, числа целые, то есть тип данных у нас будет int. Те, кто захочет реализовать решение задачи с другими типами данных, например, с double — без проблем откорректирую исходный код программы.

Второе: какой метод сортировки массива использовать?

Существует множество методов сортировки массивов: выбором, пузырьковая, гномья, вставками, перемешиванием и т.д. Учитывая, что конкретный метод сортировки не указан, будем реализовывать нашу задачу, используя один из самых простых методов сортировки — сортировку выбором.

Третье: как задаются массивы a и b?

Массив может быть задан пользователем с клавиатуры, а может быть жестко прописан в коде программы. Для упрощения, будем задавать массивы в коде программы.

Определившись с типами данных, способом получения данных и методом сортировки, приступим к выполнению лабораторной работы №1.

Решение лабораторной работы

Для того, чтобы в дальнейшем мы могли достаточно легко модифицировать наш код под другие вводные, напишем три отдельных метода, каждый из которых будет выполнять свою часть работы:

  1. Метод сортировки массива по возрастанию
  2. Метод сортировки массива по убыванию
  3. Метод объединения двух массивов в один

Технически, можно обойтись и двумя методами — вместо двух методов сортировки написать один, который будет сортировать массив в любом заданном пользователе порядке, но для наглядности пока оставим два метода, а, в дальнейшем проведем улучшение нашего кода.

Метод сортировки массива по возрастанию

В качестве параметра, метод должен получать массив целочисленных значений и сортировать его:

static void SortAscending(int[] intArray)
{
    int indx; //переменная для хранения индекса минимального элемента массива
    for (int i = 0; i < intArray.Length; i++) //проходим по массиву с начала и до конца
    {
        indx = i; //считаем, что минимальный элемент имеет текущий индекс 
        for (int j = i; j < intArray.Length; j++) //ищем минимальный элемент в неотсортированной части
        {
            if (intArray[j] < intArray[indx])
            {
                indx = j; //нашли в массиве число меньше, чем intArray[indx] - запоминаем его индекс в массиве
            }
        }
        if (intArray[indx] == intArray[i]) //если минимальный элемент равен текущему значению - ничего не меняем
            continue;
        //меняем местами минимальный элемент и первый в неотсортированной части
        int temp = intArray[i]; //временная переменная, чтобы не потерять значение intArray[i]
        intArray[i] = intArray[indx];
        intArray[indx] = temp;
    }
}

Метод реализует сортировку массива выбором.

Метод сортировки массива по убыванию

Нетрудно догадаться, как должен выглядеть метод для сортировки по убыванию, если внимательно прочитать комментарии к коду, представленному выше:

static void SortDescending(int[] intArray)
{
    int indx; 
    for (int i = 0; i < intArray.Length; i++) 
    {
        indx = i;  
        for (int j = i; j < intArray.Length; j++) 
        {
            if (intArray[j] > intArray[indx]) //заменяем знак сравнения на противоположный
            {
                indx = j; 
            }
        }
        if (intArray[indx] == intArray[i]) 
            continue;
        
        int temp = intArray[i]; 
        intArray[i] = intArray[indx];
        intArray[indx] = temp;
    }
}

Метод объединения двух массивов в один

Здесь стоит помнить, что массив в C# остается неизменным в течение всего его времени жизни после создания. Следовательно, метод объединения массива должен принимать в качестве параметров два массива, а в качестве результата — возвращать объединенный массив. Сделать это можно следующим образом:

static int[] ConcatArrays(int[] a, int[] b)
{
    int[] c = new int[a.Length + b.Length]; //длина нового массива равна сумме длин исходных массивов
    for (int i = 0; i < a.Length; i++) //переносим числа из массива A в массив C
        c[i] = a[i];
    for (int i = a.Length; i < a.Length+b.Length; i++) //переносим числа из массива B в массив C, начиная с индекса a.Length
        c[i] = b[i- a.Length]; //не забываем, что у массива B индекс очередного элемента на a.Length меньше, чем у C!
    return c;
}

Код основной программы

Теперь у нас всё готово для того, чтобы составить основной код программы. Он будет очень коротким и простым:

static void Main(string[] args)
{
    int[] a = new int[5] { 2, 4, 5, 1, 4 }; 
    int[] b = new int[5] { 9, 1, 4, -1, 2 };
    SortAscending(a); //отсортировли первый массив по возрастанию
    SortDescending(b); //отсортировали второй массив по убыванию
    int[] c = ConcatArrays(a, b); //объединили массивы
    /*Выводим итоговый массив в консоль*/
    foreach (int i in c) 
        Console.Write($"{i} ");
}

Результаты работы программы представлены ниже:

1 2 4 4 5 9 4 2 1 -1

Весь исходный код программы

Весь исходный код программы для лабораторной работы №1 представлен ниже:

using System;

namespace LabRab_1
{
    class Program
    {
        static void SortAscending(int[] intArray)
        {
            int indx; //переменная для хранения индекса минимального элемента массива
            for (int i = 0; i < intArray.Length; i++) //проходим по массиву с начала и до конца
            {
                indx = i; //считаем, что минимальный элемент имеет текущий индекс 
                for (int j = i; j < intArray.Length; j++) //ищем минимальный элемент в неотсортированной части
                {
                    if (intArray[j] < intArray[indx])
                    {
                        indx = j; //нашли в массиве число меньше, чем intArray[indx] - запоминаем его индекс в массиве
                    }
                }
                if (intArray[indx] == intArray[i]) //если минимальный элемент равен текущему значению - ничего не меняем
                    continue;
                //меняем местами минимальный элемент и первый в неотсортированной части
                int temp = intArray[i]; //временная переменная, чтобы не потерять значение intArray[i]
                intArray[i] = intArray[indx];
                intArray[indx] = temp;
            }
        }

        static void SortDescending(int[] intArray)
        {
            int indx; 
            for (int i = 0; i < intArray.Length; i++) 
            {
                indx = i;  
                for (int j = i; j < intArray.Length; j++) 
                {
                    if (intArray[j] > intArray[indx]) //заменяем знак сравнения на противоположный
                    {
                        indx = j; 
                    }
                }
                if (intArray[indx] == intArray[i]) 
                    continue;
                
                int temp = intArray[i]; 
                intArray[i] = intArray[indx];
                intArray[indx] = temp;
            }
        }

        static int[] ConcatArrays(int[] a, int[] b)
        {
            int[] c = new int[a.Length + b.Length]; //длина навого массива равна сумме длин исходных массивов
            for (int i = 0; i < a.Length; i++) //переносим числа из массива A в масси C
                c[i] = a[i];
            for (int i = a.Length; i < a.Length+b.Length; i++) //переносим числа из массива B в масси C, начиная с индекса a.Length
                c[i] = b[i- a.Length]; //не забываем, что у массива B индекс очередного элемента на a.Length меньше, чем у C!
            return c;
        }

        static void Main(string[] args)
        {
            int[] a = new int[5] { 2, 4, 5, 1, 4 }; 
            int[] b = new int[5] { 9, 1, 4, -1, 2 };
            SortAscending(a); //отсортировли первый массив по возрастанию
            SortDescending(b); //отсортировали второй массив по убыванию
            int[] c = ConcatArrays(a, b); //объединили массивы
            /*Выводим итоговый массив в консоль*/
            foreach (int i in c) 
                Console.Write($"{i} ");
        }
    }
}

Улучшения

Обратите внимание на два метода сортировки массивов — SortAscending и SortDescending. Эти методы отличаются друг от друга ровно одним символом! Конечно же, это совсем не рационально и не правильно, как минимум по двум причинам:

  1. Если потребуется изменить метод сортировки массива — придется проводить двойную работу и вносить изменения в оба метода;
  2. «Портянки» дублирующего кода — признак плохого кода.

Намного лучше, если сортировкой массива будет заниматься один метод, который на входе будет получать не только массив для сортировки, но и какой-либо параметр, указывающий на то, в каком порядке массив сортировать — для этих целей как нельзя лучше нам подойдут перечисления.  Перепишем метод сортировки массива следующим образом:

enum SortParam {ASC, DESC};

static void SortArray(int[] intArray, SortParam sortParam)
{
    int indx; 
    for (int i = 0; i < intArray.Length; i++) 
    {
        indx = i; 
        for (int j = i; j < intArray.Length; j++) 
        {
            //ASC = по возврастанию (intArray[j] < intArray[indx])
            //DESC = по убыванию (intArray[j] > intArray[indx])
            if (((intArray[j] < intArray[indx]) && (sortParam == SortParam.ASC)) || ((intArray[j] > intArray[indx]) && (sortParam == SortParam.DESC)))
            {
                indx = j; 
            }
        }
        if (intArray[indx] == intArray[i]) 
            continue;
        int temp = intArray[i];
        intArray[i] = intArray[indx];
        intArray[indx] = temp;
    }
}

Здесь метод принимает в качестве параметров массив и порядок сортировки: ASC — по возрастанию, DESC — по убыванию. Также немного изменился внутренний цикл for — условие сравнение двух элементов теперь происходит в зависимости от того, в каком порядке сортируется массив. Для составления условия при котором очередной индекс элемента будет запоминаться мы использовали условные логические операторы.

Теперь методы SortAscending и SortDescending можно убрать из программы, а основной код программы переписать вот так:

static void Main(string[] args)
{
    int[] a = new int[5] { 2, 4, 5, 1, 4 }; 
    int[] b = new int[5] { 9, 1, 4, -1, 2 };
    SortArray(a, SortParam.ASC); //отсортировали первый массив по возрастанию
    SortArray(b, SortParam.DESC);//отсортировали второй массив по убыванию
    int[] c = ConcatArrays(a, b); //объединили массивы
    /*Выводим итоговый массив в консоль*/
    foreach (int i in c) 
        Console.Write($"{i} ");
}

Теперь, когда у нас основная логика программы улучшена, можно приступить к улучшению программы с точки зрения пользователя. Удобнее было бы выводить пользователю программы не только итог работы программы, но и исходные данные, а чтобы, опять же не дублировать код вывода массива в консоль — выделим этот код в отдельный метод:

static string ArrayToString(int[] array)
{
    string s = string.Empty;
    foreach (int i in array)
        s += $"{i} ";
    return s;
}

Здесь метод возвращает в качестве результата строку, содержащую элементы массива, разделенные пробелом. Для работы со строками мы применили интерполяцию.

Полный исходный код улучшенной программы представлен ниже:

using System;

namespace LabRab_1
{
    class Program
    {
        enum SortParam {ASC, DESC};
        
        static void SortArray(int[] intArray, SortParam sortParam)
        {
            int indx; 
            for (int i = 0; i < intArray.Length; i++) 
            {
                indx = i; 
                for (int j = i; j < intArray.Length; j++) 
                {
                    //ASC = по возврастанию (intArray[j] < intArray[indx])
                    //DESC = по убыванию (intArray[j] > intArray[indx])
                    if (((intArray[j] < intArray[indx]) && (sortParam == SortParam.ASC)) || ((intArray[j] > intArray[indx]) && (sortParam == SortParam.DESC)))
                    {
                        indx = j; 
                    }
                }
                if (intArray[indx] == intArray[i]) 
                    continue;
                int temp = intArray[i]; 
                intArray[i] = intArray[indx];
                intArray[indx] = temp;
            }
        }

        static int[] ConcatArrays(int[] a, int[] b)
        {
            int[] c = new int[a.Length + b.Length]; //длина навого массива равна сумме длин исходных массивов
            for (int i = 0; i < a.Length; i++) //переносим числа из массива A в масси C
                c[i] = a[i];
            for (int i = a.Length; i < a.Length+b.Length; i++) //переносим числа из массива B в масси C, начиная с индекса a.Length
                c[i] = b[i- a.Length]; //не забываем, что у массива B индекс очередного элемента на a.Length меньше, чем у C!
            return c;
        }

        static string ArrayToString(int[] array)
        {
            string s = string.Empty;
            foreach (int i in array)
                s += $"{i} ";
            return s;
        }

        static void Main(string[] args)
        {
            int[] a = new int[5] { 2, 4, 5, 1, 4 }; 
            int[] b = new int[5] { 9, 1, 4, -1, 2 };

            Console.WriteLine($"Исходный массив A: {ArrayToString(a)}");
            SortArray(a, SortParam.ASC); //отсортировли первый массив по возрастанию
            Console.WriteLine($"Отсортированный массив A: {ArrayToString(a)}");

            Console.WriteLine($"Исходный массив B: {ArrayToString(b)}");
            SortArray(b, SortParam.DESC);//отсортировали второй массив по убыванию
            Console.WriteLine($"Отсортированный B: {ArrayToString(b)}");

            int[] c = ConcatArrays(a, b); //объединили массивы
            Console.WriteLine($"Итоговый массив С: {ArrayToString(c)}");
        }
    }
}

Результат работы программы:

Исходный массив A: 2 4 5 1 4
Отсортированный массив A: 1 2 4 4 5
Исходный массив B: 9 1 4 -1 2
Отсортированный B: 9 4 2 1 -1
Итоговый массив С: 1 2 4 4 5 9 4 2 1 -1

Итого

Сегодня мы выполнили лабораторную работу в C# по сортировке и объединению массивов. Для выполнения работы нам потребовались знания о массивах, методах их сортировки, знание логических операторов в C#, интерполяции строк. Лабораторная работа представлена в двух вариантах — подробном и улучшенном варианте, где сортировка массива происходит в том порядке, в котором её задает пользователь.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии