Ошибка удаления дубликата в C с помощью указателей - PullRequest
0 голосов
/ 09 октября 2019

У меня ошибка с моим кодом, когда я пытаюсь получить дубликаты и удалить их.

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

Внизу я отобразил два метода.

void print_array просто распечатывает массив.

void removeDups Я хочу получить дубликаты, удалить их и распечатать новый массив.

Дайте мне знать, где произошла ошибка.

Также рекомендуется использовать указатель. Спасибо!

void removeDups(int *array, int *length)
{
        *length = 10;
        int i, j;
        for(i = 0; i < *length; i++)
        {
           for(j = 0; j < *length; j++)
           {
             if(array[i] == array[j])
             {
                array[j] = array[*length-2];
                length++;
              }
            }
        }
        printf("Number of new elements: %d,", *length);
        printf(" new elements: ");
        for(i = 0; i < *length; i++)
        {
                printf("%d " , array[i]);
        }
}

void print_array(int *array, int length)
{
    printf("Number of elements: %d,", length);
    int i;
    printf(" Orginal elements: ");
    for(i = 0; i < length; i++)
    {
            printf("%d " , array[i]);
    }
}
int main()
{
    int array [10];
    int i, number;
    int size = 10;
    int *length;
    length = &size;
    for(i = 0; i < size; i++)
    {
            number = rand() % 10 + 1;
            array[i] = number;
    }
    print_array(array, size);
    printf("\n");
    removeDups(array, length);
    return 0;
}

вывод:

Количество элементов: 10, Оригинальные элементы: 4 7 8 6 4 6 7 3 10 2

Количество новых элементов: 3, новыеэлементы: 10 6 8

Ответы [ 2 ]

2 голосов
/ 09 октября 2019

Пожалуйста, исправьте все предупреждения в вашем коде - вы можете включить флаги Wall и Wextra в GCC, например.

Тогда одна логическая ошибка, которую я вижу здесь:

array[j] == array[i]

где вы хотите назначить, а не сравнивать, поэтому измените его на:

array[j] = array[i]

Более того, когда вы печатаете массив с удаленными дублирующимися значениями, вы выполняете итерацию до end, но эта переменнаяне объявлено.


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

#include <stdio.h>
#include <stdlib.h>

void removeDups(int *array, int length)
{
  int array_no_dups[length];
  int unique_n = 0;
  for(int i = 0; i < length; ++i)
  {
    int found = 0; // flag
    //check if element already in the array without duplicates
    for(int j = 0; j < unique_n; j++)
    {
      if(array[i] == array_no_dups[j])
        found = 1;
    }
    // If not found
    if(!found)
      // then append it to the array without duplicates
      array_no_dups[unique_n++] = array[i];
  }
  printf("Number of new elements: %d,", unique_n);
  printf(" new elements: ");
  for(int i = 0; i < unique_n; i++)
  {
    printf("%d ", array_no_dups[i]);
  }
}
void print_array(int *array, int length)
{
    printf("Number of elements: %d,", length);
    printf(" Orginal elements: ");
    for(int i = 0; i < length; i++)
    {
            printf("%d " , array[i]);
    }
}
int main()
{
    int array[10];
    int size = 10;
    for(int i = 0; i < size; i++)
      array[i] = rand() % 10 + 1;
    print_array(array, size);
    printf("\n");
    removeDups(array, size);
    return 0;
}

Вывод:

Number of elements: 10, Orginal elements: 4 7 8 6 4 6 7 3 10 2 
Number of new elements: 7, new elements: 4 7 8 6 3 10 2 

Теперь, если вы действительно хотите удалить дубликаты на месте, тогдакаждый раз, когда вы находите повторяющееся значение, вам нужно будет поменять 2-е вхождение этого значения на последний элемент вашего массива (который будет проиндексирован счетчиком, который вы будете поддерживать). Конечно, теперь вам нужно быть осторожным с вашими индексами.

Например, вы можете на месте вот так (вызвать метод так: removeDups(array, &size);):

void removeDups(int *array, int *length)
{
  int original_len = *length;
  for(int i = 0; i < original_len - 1; ++i)
  {
    for(int j = i + 1; j < *length; ++j)
    {
      if(array[i] == array[j])
      {
        array[j] = array[*length - 1];
        (*length)--;
        j--;  // since the new `array[j]` element might be also a duplicate of `array[i]`
      }
    }
  }
  printf("Number of new elements: %d,", *length);
  printf(" new elements: ");
  for(int i = 0; i < *length; i++)
  {
    printf("%d ", array[i]);
  }
}

Теперь вывод будет:

Количество новых элементов: 7, новых элементов: 4 7 8 6 2 3 10

где оригиналпорядок элементов не сохраняется.

Если вы хотите сделать это на месте и сохранить исходный порядок, то вместо замены каждый раз, когда вы найдете дубликат, вы должны сдвинуть весь подмассив из (j+1) -ый элемент на одну позицию слева.

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

1 голос
/ 09 октября 2019

Эта часть

 if(array[i] == array[j])
 {
   array[j] == array[i];
   length++;
 }

не имеет смысла. Выражение

array[j] == array[i];

является сравнением. Я предполагаю, что вы хотели повлиять на array[i] до array[j] с

array[j] = array[i];

, но вы просто подтвердили, что они были одинаковыми.
Затем вы увеличиваете length, чтоопасно и бессмысленно в этом контексте.

Если порядок не важен, замените array[j] на array[length - 1], затем уменьшите length.
Если порядок важен, переместите каждое значение с array[j + 1] на array[length - 1] в array[j] на array[length - 2], затем уменьшите length.

Также удалите строку

length = 10;

. Здесь length уже равно 10, когда вы вызываете removeDups, и если вы вызываете его с меньшим массивом, вы будете читать вне вашего массива. Вам также нужно только сравнить значение со значениями после него;при сравнении array[i] оно уже сравнивалось со всеми значениями от array[0] до array[i - 1].

for(i = 0; i < *length; i++)
{
        for(j = i + 1; j < *length; j++)
        {
                if(array[i] == array[j])
                {
                        array[j] = array[*length - 1];
                        (*length)--;
                }       
        }
}

Отредактировано: Riiight, длина int *!

Упорядоченоверсия:

for(i = 0; i < *length; i++)
{
        for(j = i + 1; j < *length; j++)
        {
                if(array[i] == array[j])
                {
                        for (int k = j; k < *length - 1; ++k)
                        {
                                array[k] = array[k + 1];
                        }
                        (*length)--;
                        j--; //I forgot this, but once you moved all values array[j] will have been updated and you must compare it again.
                }       
        }
}

Или используйте вторичный массив, как подсказывает gsamaras.

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