简体   繁体   中英

how to compare two arrays in c?

I am creating a function which can compare two arrays. It returns 1 when they are the same and return 0 when they are not.

It required the program run as linear time, so i cannot use a for-for loop to compare it. Any suggestions for me?

Examples of arrays for which scrambled should return 1:

a = {10,15,20}, b = {10,15,20}
a = {1,2,3,4,5}, b = {5,3,4,2,1}
a = {}, b = {} (i.e. len = 0)
a = {2,1,3,4,5}, b = {1,2,4,3,5}

Examples of arrays for which scrambled should return 0:

a = {1,1}, b = {1,2}
a = {10,15,20}, b = {10,15,21}
a = {1,2,3,4,5}, b = {5,3,4,2,2}

If you can specify a maximum value for the array elements, you can compare them in linear time pretty easily, by just looping through each one and counting the values which are present, like so:

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

#define MAX_ARRAY_VALUE 100

bool compare_arrays(int * arr1, size_t arr1_size,
                    int * arr2, size_t arr2_size)
{

    /*  Set up array to count elements  */

    int * table = calloc(MAX_ARRAY_VALUE + 1, sizeof * table);
    if ( !table ) {
        perror("couldn't allocate memory");
        exit(EXIT_FAILURE);
    }

    /*  Increment index if element is present in first array...  */

    for ( size_t i = 0; i < arr1_size; ++i ) {
        table[arr1[i]]++;
    }

    /*  ...and decrement index if element is present in second array.  */

    for ( size_t i = 0; i < arr2_size; ++i ) {
        table[arr2[i]]--;
    }

    /*  If any elements in array are not zero, then arrays are not equal  */

    for ( size_t i = 0; i < MAX_ARRAY_VALUE + 1; ++i ) {
        if ( table[i] ) {
            free(table);
            return false;
        }
    }

    free(table);
    return true;
}

int main(void) {
    int a1[] = {10, 20, 30, 10};
    int a2[] = {20, 10, 10, 30};
    int a3[] = {1, 4, 5};
    int a4[] = {1, 3, 5};

    if ( compare_arrays(a1, 4, a2, 4) ) {
        puts("a1 and a2 are equal");        /*  Should print  */
    }
    else {
        puts("a1 and a2 are not equal");    /*  Should not print  */
    }

    if ( compare_arrays(a3, 3, a4, 3) ) {
        puts("a3 and a4 are equal");        /*  Should not print  */
    }
    else {
        puts("a3 and a4 are not equal");    /*  Should print  */
    }

    if ( compare_arrays(a1, 4, a4, 3) ) {
        puts("a1 and a4 are equal");        /*  Should not print  */
    }
    else {
        puts("a1 and a4 are not equal");    /*  Should print  */
    }

    return 0;
}

which outputs:

paul@horus:~/src/sandbox$ ./lincmp
a1 and a2 are equal
a3 and a4 are not equal
a1 and a4 are not equal
paul@horus:~/src/sandbox$ 

Without specifying the maximum value, you can loop through each array and find the maximum. It'll still be linear time, but without an upper bound you might end up with a huge index table.

Because the comparison of the two arrays is independent of the order of the elements, both must be sorted before they can be compared. Because of this, you can't do this in linear time. The best you can do is O(n log n) , as that is the best order of most sorting algorithms.

My C is pretty rusty so the may be some memory problem with the script below. However, the basic task is to sort the 2 arrays, compare them element by element. If they all match, scramble should return 1, other it's 0.

The script below works with GCC, haven't tested it with any other compiler. It compares arrays of equal length. The case of unequal length is left for the OP as an minor exercise.

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

int compare_ints(const void * a , const void * b)
{
    const int * ia = (const int *)a;
    const int * ib = (const int *)b;
    return *ia > *ib;
}

int scramble(const int * a, const int * b, unsigned int len)
{
    int * sorted_a = malloc(len * sizeof(int));
    int * sorted_b = malloc(len * sizeof(int));

    memcpy(sorted_a, a, len * sizeof(int));
    memcpy(sorted_b, b, len * sizeof(int));

    qsort(sorted_a, len, sizeof(int), compare_ints);
    qsort(sorted_b, len, sizeof(int), compare_ints);

    for (int i = 0; i < len; i++)
    {
        if (sorted_a[i] != sorted_b[i])
        {
            free(sorted_a);
            free(sorted_b);
            return 0;
        }
    }

    free(sorted_a);
    free(sorted_b);
    return 1;
}

int main (int argc, char const *argv[])
{
    int a[3] = {20, 10, 15};
    int b[3] = {10, 15, 20};
    int is_equal = scramble(a, b, 3);

    printf("is_equal = %i\n", is_equal);
    return 0;
}

FYI: you can't do it in linear time. qsort has O(n log n) .

At a certain extent, you can obtain the sum of all the hashed values of the first array, and compare it to the sum of the hashed values of the second array. It'll work, but I don't know precise it is.

Here is my attempt, all my tests have given positive results so far :

#include <stdio.h>

unsigned int hash(unsigned int x) {
    x = ((x >> 16) ^ x) * 0x45d9f3b;
    x = ((x >> 16) ^ x) * 0x45d9f3b;
    x = ((x >> 16) ^ x);
    return x;
}

int compareArrays(int *arr1, int *arr2, int size) {

    if (size == 0) return 1;

    unsigned long  sum1 = 0;
    unsigned long  sum2 = 0;

    for (int i = 0; i < size; ++i)  {
        sum1 += hash(arr1[i]);
    }
    for (int i = 0; i < size; ++i) 
        sum2 += hash(arr2[i]) ;

    return sum1 == sum2;
}

int main(void) {
    int a[] = {1,2,3,4,5,6,7,8,255};
    int b[] = {1,2,3,4,5,6,7,8,9};
    int size = 9;
    printf("Are they the same? %s.\n", compareArrays(a, b, size) ? "yes" : "no");
    return 0;
}

You can use memcmp function with this format:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

For example;

/* memcmp example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char buffer1[] = "abcde";
  char buffer2[] = "abcde";

  int n;

  n=memcmp ( buffer1, buffer2, sizeof(buffer1) );

  if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
  else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
  else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);

  return 0;
}

output is:

'abcde' is same as 'abcde'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM