Сравнение 2 массивов, чтобы выяснить, имеют ли они одинаковые элементы или нет

#c

Вопрос:

Я начинающий программист, и мне нужна была помощь с упражнением! Как вы видели в названии, в упражнении предлагается написать программу, которая сравнивает элементы 2 массивов, чтобы выяснить, имеют ли они одинаковые элементы или нет. Хитрость заключается в том, что элементы во 2-м массиве могут располагаться не в том порядке, что и в первом массиве. Я подумал, что, возможно, один из способов исправить это — переставить 2 массива, чтобы они были в порядке возрастания, но по какой-то причине он продолжает говорить, что массивы имеют одинаковые элементы. Вы можете мне помочь?

Это код:

 int main()
{
    int v[N];
    int v2[N];
    int i,j;
    int a;
    int b;
    int flag = 0;

    printf("Please enter the values of the 1st array: ");

    for (i = 0; i < N; i  )
    {
        scanf("%d",amp;v[i]);
    }

    for (i = 0; i < N; i  )
    {
        for(j=i 1; j<N; j  )
        {
            if(v[i]>v[j])
            {
                a = v[i];
                v[i] = v[j];
                v[j] = a;
            }
        }
    }

    printf("nPlease enter the values of the 2nd array: ");
    
    for (i = 0; i < N; i  )
    {
        scanf("%d", amp;v2[i]);
    }

    for (i = 0; i < N; i  )
    {
        for (j = i   1; j < N; j  )
        {
            if (v2[i] > v2[j])
            {
                b = v2[i];
                v2[i] = v2[j];
                v2[j] = b;
            }
        }
    }

    for (i = 0; i < N; i  )
    {
        for (j = 0; j < N; j  )
        {
            if (v[i] == v2[j])
            {
                flag=1;
            }
        }
    }

    if (flag == 1)
        printf("nThe arrays have the same numbers! ");
    else
        printf("nThe arrays dont have the same numbers!");

    return 0;
}
 

Комментарии:

1. «Не работает» никогда не является хорошим описанием проблемы. Какие ошибки или неправильное поведение вы получаете? И выполняли ли вы какую-либо базовую отладку, чтобы ответить на основные вопросы, такие как правильны ли входные массивы, правильно ли отсортирован массив, сравниваются ли правильные значения и т. Д.? Как отлаживать небольшие программы .

2. Хорошо, я изменил текст. Проблема в том, что он продолжает говорить, что массивы имеют одинаковые элементы, если только 3 элемента не являются совершенно разными. Если хотя бы один из них одинаков, это говорит о том, что они имеют одинаковые элементы

3. А как насчет отладки? Вы выполняли какую-либо базовую отладку? Обратите внимание, что простой запуск программы не является отладкой (это тестирование). Просмотрите код в отладчике и / или добавьте дополнительные инструкции debug print для отслеживания потока программы и значений переменных, чтобы выяснить, где что-то пошло не так.

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

5. В этом все дело. Я попытался найти, в чем может заключаться проблема, в моей голове, согласно тому, что я думаю, я сделал это правильно. Я беру один элемент из 1-го массива и сравниваю его со всеми элементами 2-го массива, и если он совпадает, я устанавливаю флаг равным 1 и перехожу ко 2-му элементу и так далее. Проблема заключается в том, как я написал сравнение, но я не могу понять, как его правильно написать.

Ответ №1:

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

Вы должны использовать гораздо более простой цикл сравнения, сравнивая v[i] и v2[i] для i изменения от 0 до N исключено.

Вот модифицированная версия:

 #include <stdio.h>

#define N  100

int main() {
    int v[N];
    int v2[N];
    int i, j;
    int flag;

    printf("Please enter the values of the 1st array: ");

    for (i = 0; i < N; i  ) {
        if (scanf("%d", amp;v[i]) != 1)
            return 1;
    }

    for (i = 0; i < N; i  ) {
        for (j = i   1; j < N; j  ) {
            if (v[i] > v[j]) {
                int a = v[i];
                v[i] = v[j];
                v[j] = a;
            }
        }
    }

    printf("nPlease enter the values of the 2nd array: ");
    
    for (i = 0; i < N; i  ) {
        if (scanf("%d", amp;v2[i]) != 1)
            return 1;
    }

    for (i = 0; i < N; i  ) {
        for (j = i   1; j < N; j  ) {
            if (v2[i] > v2[j]) {
                int b = v2[i];
                v2[i] = v2[j];
                v2[j] = b;
            }
        }
    }

    flag = 1;
    for (i = 0; i < N; i  ) {
        if (v[i] != v2[i]) {
            flag = 0;
            break;
        }
    }

    if (flag == 1)
        printf("nThe arrays have the same numbers! ");
    else
        printf("nThe arrays dont have the same numbers!");

    return 0;
}
 

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

 #include <stdio.h>

#define N  100

int count(const int *v, int len, int x) {
    int n = 0;
    for (int i = 0; i < len; i  ) {
        n  = (v[i] == x);
    }
    return n;
}

int main() {
    int v[N];
    int v2[N];
    int i;
    int flag;

    printf("Please enter the values of the 1st array: ");

    for (i = 0; i < N; i  ) {
        if (scanf("%d", amp;v[i]) != 1)
            return 1;
    }

    printf("nPlease enter the values of the 2nd array: ");
    
    for (i = 0; i < N; i  ) {
        if (scanf("%d", amp;v2[i]) != 1)
            return 1;
    }

    flag = 1;
    for (i = 0; i < N; i  ) {
        if (count(v, N, v[i]) != count(v2, N, v[i])) {
            flag = 0;
            break;
        }
    }

    if (flag == 1)
        printf("nThe arrays have the same numbers! ");
    else
        printf("nThe arrays dont have the same numbers!");

    return 0;
}
 

Ответ №2:

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

 for(i=0;i<N;i  )
{
    for(j=0;j<N;j  )
    {
        if(v[i]==v2[j])
        {
            flag=1;
        }
    }
}
 

Это говорит о том, что для каждого элемента в первом массиве проверьте каждый элемент во втором массиве; если он равен элементу в первом массиве, то установите flag = 1 . По сути, он возвращает true, если КАКОЙ-либо из элементов одинаков в двух массивах.

Комментарии:

1. Тогда как бы вы предложили мне это сделать?

2. Когда вы просматриваете элементы массива, вы хотите проверить один и тот же индекс в обоих массивах. Поэтому вы должны использовать только один цикл for с одной переменной. В этом цикле for вы должны проверить, совпадают ли v[i] и v2 [i], и если для них установлен флаг, равный 1, и выйти из цикла (если вы не знаете, как это сделать, все в порядке; для программы не требуетсяработает правильно, только для повышения эффективности).

Ответ №3:

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

Вы можете создать массив целых чисел той же длины, что и сравниваемые массивы, и использовать их в качестве флагов, чтобы проверить, «использовали» ли вы индекс во втором массиве при проверке элементов в первом массиве.

Мы увидим это для всех 0 , затем, когда мы сканируем первый массив, мы будем игнорировать любые индексы во втором массиве, которые уже использовались. Если мы найдем совпадение, мы установим флаг, указывающий, что индекс в массиве 2 использовался, и мы прервем внутренний цикл, чтобы избавить себя от дальнейших итераций по второму массиву.

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

int arrays_match(int *arr1, int *arr2, int n) {
    size_t used[n];

    /* Initialize the used array to all 0 or false. */
    for (int i = 0; i < n; i  ) {
        used[i] = 0;    
    }

    for (int i = 0; i < n; i  ) {
        int in_both = 0;

        for (int j = 0; j < n; j  ) {
            if (used[j] == 0 amp;amp; arr1[i] == arr2[j]) {
                in_both = 1;
                used[j] = 1;
                break;
            }
        }

        if (!in_both) return 0;
    }

    return 1;
}

int main() {
    int a[4] = { 1, 2, 3, 4 };
    int b[4] = { 4, 2, 3, 1 };

    if (arrays_match(a, b, 4)) {
        printf("Huzzah!n");
    }
    else {
        printf("Huh?n");
    }
}
 

В итоге выводится «Ура!», Но если мы инициализируем a с { 4, 2, 2, 1 } помощью then, он печатает «А?»

Рассмотрим, что происходит, когда мы запускаем приведенный ниже пример.

 a = { 1, 2, 4, 2 }
b = { 4, 2, 2, 1 }
used = { 0, 0, 0, 0 }
 

Внешний цикл имеет дело с a[0] первым, то есть 1 . Он выполняет итерацию по внутреннему циклу до j тех пор, пока не будет 3 , и в этот момент он как находит совпадение, так и used[3] остается 0 .

 a = { 1, 2, 4, 2 }
b = { 4, 2, 2, 1 }
used = { 0, 0, 0, 1 }
 

Теперь внешний цикл проверяет a[1] , что есть 2 . Он проверяет b , пока не дойдет до b[1] и used[1] есть 0 , поэтому он находит совпадение.

 a = { 1, 2, 4, 2 }
b = { 4, 2, 2, 1 }
used = { 0, 1, 0, 1 }
 

Затем внешний цикл проверяет a[2] , что есть 4 . Он проверяет b , пока не дойдет до b[0] и used[0] есть 0 , поэтому он находит совпадение.

 a = { 1, 2, 4, 2 }
b = { 4, 2, 2, 1 }
used = { 1, 1, 0, 1 }
 

Наконец, внешний цикл проверяет a[3] , что снова 2 . Он проверяет b , пока не дойдет до b[1] того, что также 2 есть , но used[1] есть 1 , поэтому он не может найти совпадение здесь. Он продолжает b[2] и находит совпадение, потому used[2] что все еще 0 .

 a = { 1, 2, 4, 2 }
b = { 4, 2, 2, 1 }
used = { 1, 1, 1, 1 }
 

Итерация завершена, и никаких несоответствий обнаружено не было. Функция возвращает 1 (true).