Как удалить дубликаты (с оригинальным значением) из вектора в C ++ - PullRequest
0 голосов
/ 28 мая 2018

Я написал программу для удаления дубликатов из заданного набора чисел.но я не получаю требуемый вывод. Вместо этого я получаю ошибку времени выполнения SIGSTP каждый раз.Формат ввода / вывода выглядит примерно так: input: 1 2 5 7 1 4 2 output: 5 7 4 мой код указан ниже:

#include <iostream>
#include<string>
#include <vector>
using namespace std;

int main() {
    // your code goes here
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        cin >> n;
        vector<int> v_num;
        for(int i=0;i<n;i++)
        {
            int x;
            cin >> x;
            v_num.push_back(x);
       }
       vector<int>::iterator it;
       for(it=v_num.begin();it!=v_num.end();)
       {
           int val=*it;
           int flag=0;
           vector<int>:: iterator j;
           for(j=it+1;j!=v_num.end();)
           {
               if(val==*j)
               {
                   v_num.erase(j);
                   flag=1;
               }
               if(flag==0)
                  j++;
           }
           if(flag==1)
                { v_num.erase(it);
                 flag=1;}
           if(flag==0)
                 it++;
       }

        for(int i=0;i<v_num.size();i++)
           { cout <<v_num[i]<<endl;
            }
    }

}

это мой первый вопрос на онлайн-платформе, поэтому иногда яможет быть не ясноВ этом случае любое предложение или дальнейшие разъяснения могут быть размещены в разделе комментариев.Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

Проблема вашего кода в том, что вы удаляете элементы и позже используете итераторы.

например,

       for(j=it+1;j!=v_num.end();)
       {
           if(val==*j)
           {
               v_num.erase(j);

Я просто скопировал и вставил его из вашего кода.Вы стираете j, и на следующей итерации вы снова используете it, что, скорее всего, неверно

Стирание из вектора делает недействительными итераторы.

Это один из случаев, когда вам следуетиспользуйте std::list вместо std::vector

0 голосов
/ 28 мая 2018

Вам может понадобиться что-то вроде этого

vector<int> vec{1,1,2,3,4,4,2,5,6};
sort(begin(vec), end(vec));
auto last = unique(begin(vec), end(vec));
vec.erase(last, end(vec));

, чтобы заставить std :: unique работать, диапазон должен быть предварительно отсортированРЕДАКТИРОВАТЬ: я вижу, что я не сделал то, что требовал вопрос, потому что я искал другой ответ.Мне удалось написать функцию, которая возвращает вектор с уникальными числами, но он выделяет временный счетный массив и в итоге копирует элементы из вектора, которые были уникальными.Любые комментарии по этому поводу приветствуются.

template<typename T>
std::vector<T> erase_duplicated(const std::vector<T>& vec)
{
    const size_t n = vec.size();
    int* duplicates = new int[n];
    for(size_t i = 0; i < n; ++i) duplicates[i] = 0;

    for(size_t i = 0; i < n; ++i)
    {
        for(size_t j = i + 1; j < n; ++j)
            if(vec[i] == vec[j])
            {
               ++duplicates[i];
               ++duplicates[j];
            }
    }
    std::vector<T> temp;
    for(size_t i = 0; i < n; ++i)
    {
        if(!duplicates[i])
            temp.push_back(vec[i]);
    }
    delete [] duplicates;
    return temp;
}
0 голосов
/ 28 мая 2018

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

Короче говоря, когда вы вызываете erase для вектора, оба итератора it и j становятся недействительными и не должны использоваться.

Вы можете использовать std::unique или просто использовать std::set для хранения уникальных значений для начала, избегая вектора вместе, поскольку вы читаете значения всего несколькими строками выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...