从向量中删除元素时出错

时间:2014-05-06 00:39:31

标签: c++ vector

我正在尝试一种方法,我必须从整数向量中删除一个数字,并将该数字作为参数传递。我现在遇到的问题是,当我尝试在连续的位置删除相同的数字时,只删除其中一个。

例如:

vector =(1,2,2,3,4,5)我想删除数字“2”,结果将是:

vector =(1,2,3,4,5)

但如果数字不在连续的位置,方法可以正常工作:

vector =(1,2,3,2,4,5)--->删除“2”

vector =(1,3,4,5)

我的代码是:

void deleteNumber(int n, vector<int> &numbers)
{
    bool hasEntered = false;

    int counter = 0;
    vector<int> deletedNumbers;

    for(unsigned i = 0; i < numbers.size(); i++)
    {
        if(numbers[i] != n)
        {
            counter++;
        }

        else
        {
            counter = 0;
            int counter2 = 0;
            bool deleted = false;

            for(unsigned j = 0; j < deletedNumbers.size() && deleted == false; j++) // Check if a number has been deleted before
            {
                if(deletedNumbers[j] != n)
                {
                    counter2++;
                }

                else
                {
                    deleted = true;
                    counter2 = 0;
                }
            }

            if(counter2 == (int) deletedNumbers.size()) // Remove the number if it hasn't been removed
            {
                deletedNumbers.push_back(n);
                for(unsigned k = 0; k<numbers.size(); k++)
                {
                    if(numbers[k]  == n)
                        numbers.erase(numbers.begin()+k);
                }

                counter2 = 0;
                hasEntered = true;
            }
        }
    }
}

我认为错误可能是在最后一个的情况下,我最终删除了数字。

使用计数器来确定是否找到了元素。而且该方法还必须检查项目之前是否已被删除。

如果你不明白,请问我。

提前致谢:)

6 个答案:

答案 0 :(得分:1)

您的代码看起来过于复杂,因此可能包含许多错误。

这将删除n的所有实例; O(numbers.size()):

void deleteNumber(int n, vector<int> &numbers) {
  int i = 0;
  for (int j = 0; j < numbers.size(); ++j) {
    if (numbers[j] != n) numbers[i++] = numbers[j];
  }
  numbers.resize(i);
}

这将删除每次运行中的第一个n实例; O(numbers.size()):

void deleteNumber(int n, vector<int> &numbers) {
  int i = 0;
  for (int j = 0; j < numbers.size();) {
    if (numbers[j] == n) {
      for (++j; j < numbers.size() && numbers[j] == n; ++j) {
        numbers[i++] = numbers[j];
      }
    } else {
      numbers[i++] = numbers[j++];
    }
  }
  numbers.resize(i);
}

这将删除n的第一个实例; O(numbers.size()):

void deleteNumber(int n, vector<int> &numbers) {
  int i = 0;
  for (int j = 0; j < numbers.size(); ++j) {
    if (numbers[j] == n) {
      for (++j; j < numbers.size(); ++j) {
        numbers[i++] = numbers[j];
      }
      break;
    }
    numbers[i++] = numbers[j];
  }
  numbers.resize(i);
}

选择您需要的任何一个。

请注意,其他答案,例如luk32的答案包含更简单的代码(使用更多STL)来删除n的第一个实例。

如果您想在代码中查找并修复错误,我建议您尝试找到失败的非常短的输入向量,然后在调试器中单步执行它。

答案 1 :(得分:1)

你可以尝试这样的事情:

void deleteNumber(int n, vector<int> &numbers)
{
    vector<int>numbers_without_n;
    for(unsigned i = 0; i < numbers.size(); i++)
        if(numbers[i] != n)
            numbers_without_n.push_back(numbers[i]);

    numbers = numbers_without_n;
}

答案 2 :(得分:0)

你不需要在循环中有一个循环。处理删除的最简单方法是一次删除一个项目,并意识到这意味着您在删除项目时不希望增加i。取消for循环中i增量的最简单方法是首先使用--i递减它。所以你循环变成

  • 检查项目是否与数字
  • 匹配
  • 如果是,请删除该项目并减少我

答案 3 :(得分:0)

使用std :: remove和vector :: erase

#include <algorithm>

void deleteNumber(int n, vector<int>& numbers)
{
   numbers.erase(std::remove(numbers.begin(), numbers.end(), n), numbers.end());
}

答案 4 :(得分:0)

好的,因为显然std::vector::erase确实存在,我会使用标准的c++功能:

void deleteNumber(int n, vector<int> &numbers) {
 auto it = find(std::begin(numbers), std::end(numbers), n);
 if(it != numbers.end()) numbers.erase(it);
}

编辑:忘记end()不是erase的有效参数。

答案 5 :(得分:0)

首先,我不确定使用什么计数器和计数器2 - 如果他们只是用于确定你是否已经迭代到向量的末尾而没有找到元素,那么你不需要它们。

为了检查数字是否已被删除&#39;,您只需在方法的最顶部使用一个布尔变量,即不在for循环的范围内。

我相信以下内容:

if(counter2 == (int) deletedNumbers.size()) // Remove the numbers if it hasn't been removed

可以替换为if(!deleted)。

所以,这里是一个“固定的”&#39;版本,同时尝试根据您的代码注释尽可能接近现有逻辑。这可能不是最有效/优雅的实现,但我相信我已经看到了一些其他答案,它们使用STL库中的算法来实现同样的目标。

void deleteNumber(int n, vector<int> &numbers)
{
    bool deleted = false;

    for(unsigned i = 0; i < numbers.size(); i++)
    {
        if (numbers[i] == n)  // If we've found an instance of the number we're trying to delete
        {
            if (!deleted)  // Check if an instance has already been deleted
            {
                numbers.erase(numbers.begin() + i);  // Remove the number
                deleted = true;  // Flag that we have deleted an instance of the number
            }
        }
    }
}

或者,不要使用标记来删除&#39;为了防止在第一个实例之后删除数字,您可以通过在删除第一个实例后返回来进行优化 - 这将阻止循环的其余部分执行。