Удалить из массива элемент (С++)

Помечено: ,

  • В этой теме 0 ответов, 1 участник, последнее обновление 1 месяц, 3 недели назад сделано Васильев Владимир Сергеевич.
Просмотр 0 веток ответов
  • Автор
    Сообщения
    • #7070
      @admin

      Для определенности, удалим из массива первый отрицательный элемент.

      Без использования STL

      Алгоритм удаления элемента сводится к сдвигу на одну позицию влево всех элементов, расположенных правее удаляемого. Подробно алгоритм рассмтрен в теме «Алгоритм: удаление элемента массива«. Тут приведем лишь иллюстрацию:

      Для начала найдем позицию удаляемого числа — функция возвращает позицию или -1 если такого числа нет:

      int first_negative_pos(int* numbers, int size) {
        for (int i = 0; i < size; ++i) {
          if (numbers[i] < 0)
            return i;
        }
        return -1;
      }

      Алгоритм удаления с помощью сдвига можно описать на Си так:

      void remove_nth(int* numbers, int& size, int pos) {
        if (size <= pos)
          return;
        for (int i = pos; i < size-1; ++i) {
          numbers[i] = numbers[i+1];
        }
        --size;
      }

      В функции main получим позицию первого отрицательного элемента и если это положительное число — вызовем remove_nth:

        int negativePos = first_negative_pos(numbers, size);
        if (negativePos < 0) {
          printf("no negative elements\n");
        }
        else {
          remove_nth(numbers, size, negativePos);
          printf("array after remove negative: \n");
          print_array(numbers, size);
        }

      С использованием STL

      В стандартной библиотеке C++ есть вектора, имеющие метод erase, на вход которого подается итератор удаляемого элемента. Кроме того, в стандартной библиотеке есть алгоритм для поиска элемента по условию. В итоге с использованием векторов задачу можно решить так:

      #include <vector>
      #include <algorithm>
      #include <iostream>
      using namespace std;
      
      void print(const vector<int>& vec) {
          for (auto value : vec) {
              cout << value << " ";
          }
          cout << endl;
      }
      
      int main()
      {
          vector<int> vec({2,3,4,-1,-4,3,4,-5});
          print(vec);
          
          auto negative_it = find_if(vec.begin(), vec.end(), [](int value) { return value < 0; });
          vec.erase(negative_it);
          
          print(vec);
      }
      

      Алгоритмы С++ можно применять и к массивам в стиле Си, однако выглядит это весьма куцо. Для поиска можно применить тот же find_if, при этом вместо итераторов можно передать адреса начала и конца массива. Удаление реализует алгоритм std::remove (работать будет также как наша функция сдвига). Этот алгоритм не удаляет элемент физически, а лишь сдвигает его в конец, поэтому несмотря на применение алгоритмов, мы должны сами позаботиться об изменении размера массива (в Си иначе и быть не может):

      void remove_first_negative(int* arr, int& size) {
        auto negative_it = find_if(arr, arr+size, [](int value) { return value < 0; });
        std::remove(negative_it, arr+size, *negative_it);
        --size;
      }
      
      int main()
      {
          int n = 8;
          int arr[n] = {2,3,4,-1,-4,3,4,-5};
          
          print_array(arr, n);
          
          remove_first_negative(arr, n);
          
          print_array(arr, n);
      }

      В любом случае, если знать как устроены алгоритмы STL — то можно сократить объем кода и меньше работать. Несмотря на то, что алгоритмы работают с Си-контейнерами — лучше так не делать (порог вхождения у полученного кода будет весьма высоким). Узнать много полезного про STL можно в статье «Практика: алгоритмы и стандартная библиотека C++«.

Просмотр 0 веток ответов
  • Для ответа в этой теме необходимо авторизоваться.
×