从arraylist中删除重复项

时间:2017-12-01 23:02:36

标签: c arraylist duplicates

我正在尝试从ArrayList中删除重复项。每个元素重复不超过5次。为什么每个副本总是留下2个? (0,0,1,2,2,3,3,4,4,5)。

void quitarRepetidos_lista(ArrayList* lista)
{
    eNumero* auxNumero;
    eNumero* auxNumero2;
    int i,j;

    if ( lista != NULL  )
    {
        for (i = 0; i<lista->len(lista); i++)
        {
            auxNumero = lista->get(lista,i);
            for ( j = i+1; j<lista->len(lista); j++ )
            {
                auxNumero2 = lista->get(lista,j);
                if ( numero_compare(auxNumero,auxNumero2) == 0)
                {
                    lista->remove(lista,j);
                }
            }
        }
    }
}
int numero_compare(eNumero* numeroAlfa, eNumero* numeroBeta)
{
    if ( ((eNumero*)numeroAlfa)->numero >((eNumero*)numeroBeta)->numero )
    {
        return 1;
    }
    if ( ((eNumero*)numeroAlfa)->numero < ((eNumero*)numeroBeta)->numero )
    {
        return -1;
    }
    return 0;
}

应该说012345

3 个答案:

答案 0 :(得分:1)

忽略你的代码在C中不正确的事实(你在调用指针上的方法,例如lista->remove(...)但是C没有对象)。

这只是猜测,因为我们无法知道ArrayList类的实现或接口(奇怪地模仿Java SDK中的名称)但是当你做

lista->remove(lista,j);

通常会使j之后的所有元素都移回一个位置(因为你要删除第j 然后(j + 1)-th 变成第j ,填补空洞。)

          j
+---+---+---+---+---+---+
| A | B | C | D | E | F |
+---+---+---+---+---+---+

erase element at j

          j
+---+---+---+---+---+
| A | B | D | E | F |
+---+---+---+---+---+

for loop body ends, j is incremented

              j
+---+---+---+---+---+
| A | B | D | E | F |
+---+---+---+---+---+

D has been skipped

但是因为你在一个循环中,j然后由forforrthought增加,有效地跳过一个元素。你应该做点什么:

for ( j = i+1; j < lista->len(); /* no after thought */) {
  if (are equal)
    lista->remove(j);
  else
    ++j;

如果你刚删除了一个元素,那么你就不会增加j,因为下一个元素将被置于j

答案 1 :(得分:1)

从列表中删除一个元素后,不应该增加j,否则你最终会跳过下一个元素(它接受刚删除的元素的索引)。

而不是:

if ( numero_compare(auxNumero,auxNumero2) == 0)
{
    lista->remove(lista,j);
}

只有在删除元素时才应减少j

if ( numero_compare(auxNumero,auxNumero2) == 0)
{
    lista->remove(lista,j--);
}

答案 2 :(得分:1)

  

它崩溃了……

除了Jack和frslm处理的错误之外,ArrayList.c, function resizeDown()中还存在错误。

  1. newLen = (pList->reservedSize - pList->size);
    由于当有超过AL_INCREMENT个未使用的元素(请参阅contract())时,将缩小列表的保留大小,因此必须将reservedSize减少AL_INCREMENT而不是减少pList->size,后者导致通往小型newLen的道路。正确:
    newLen = pList->reservedSize - AL_INCREMENT;
  2. pList->size = newLen;
    由于功能resizeDown()仅用于缩小列表的分配空间,而不是从列表中删除元素(contract()已经做了),因此newLen必须分配给reservedSize而不是pList->size。正确:
    pList->reservedSize = newLen;