简体   繁体   中英

inversion count mergesort in C

A permutation of integers from 1 to n is a sequence a1, a2, ..., an, such that each integer from 1 to n is appeared in the sequence exactly once.

Two integers in а permutation form an inversion, when the bigger one is before the smaller one.

As an example, in the permutation 4 2 7 1 5 6 3, there are 10 inversions in total. They are the following pairs: 4–2, 4–1, 4–3, 2–1, 7–1, 7–5, 7–6, 7–3, 5–3, 6–3.

Input n and array[n] 2<=n<=100,000

First I solved problem with bubble sorting but then i met time complexity problem.

Second I solved it mergesort but I didn't do well

Here is my cord

#include <stdio.h>
#include <malloc.h>
int n;

void sizein(){
    scanf("%d",&n);
}

int count=0;
static void merge(int data[],int p,int q,int r){
    int i,j,l;
    int k=p;
    int sorted[n];
    for(i=p,j=q+1;i<=q&&j<=r;){
        sorted[k++]=(data[i]<=data[j]) ? data[i++]:data[j++];
        if(data[i>data[j]]){
            count+=q-i;
        }
    }
    if(i>q){
        for(l=j;l<=r;l++,k++){
            sorted[k]=data[l];
        }
    }
    else{
        for(l=i;l<=q;l++,k++){
            sorted[k]=data[l];
        }
    }
    for(l=p;l<=r;l++){
        data[l]=sorted[l];
    }
}

void merge_sort(int data[],int p,int r){
    if(p<r){
        int q=(p+r)/2;
        merge_sort(data,p,q);
        merge_sort(data,q+1,r);
        merge(data,p,q,r);
    }
}

int main(void){
    int i;
    int data[n];
    for(i=0;i<n;i++){
        scanf("%d",&data[i]);
    }
    merge_sort(data,0,n);
    printf("%d",count);
    return 0;
}

Where should i fix it

I cannot find some implementation bits in your code that divides the arrays into sub-arrays based on the index(as quick sort sorts based on value) kindly have a look at the code provided below

int q = p + (r - l) / 2;//recommended to be used in the function mergesort
int q=(p+r)/2;//your implementation

try this code for your function part as my code runs well with over half a million values, I cannot clearly see any subarray to which values are copied in your implementation of the function merge I have added comments to make it easier for you to understand, the terminology of the variables are slightly different.

refer "ANANY LEVETIN-INTRODUCTION TO THE DESIGN AND ANALYSIS OF ALGORITHS" book for a vivid explanation on this algorithm

Have a look and try this

void merge(int arr[], int l, int m, int r)
{
    int i, j, k;
    int n1 = m - l + 1;
    int n2 = r - m;
 
    /* create temp arrays */
    int L[n1], R[n2];
 
    /* Copy data to temp arrays L[] and R[] */
    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];
 
    /* Merge the temp arrays back into arr[l..r]*/
    i = 0; // Initial index of first subarray
    j = 0; // Initial index of second subarray
    k = l; // Initial index of merged subarray
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        }
        else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }
 
    /* Copy the remaining elements of L[], if there
    are any */
    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }
 
    /* Copy the remaining elements of R[], if there
    are any */
    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
}

/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
    if (l < r) {
        // Same as (l+r)/2, but avoids overflow for
        // large l and h
        int m = l + (r - l) / 2;
 
        // Sort first and second halves
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
 
        merge(arr, l, m, r);
    }
}
 

/* Driver code */
int main()
{
    int arr[] = { 12, 11, 13, 5, 6, 7 };
    int arr_size = sizeof(arr) / sizeof(arr[0]);
 
    printf("Given array is \n");
    //printArray(arr, arr_size);
 
    mergeSort(arr, 0, arr_size - 1);
 
    printf("\nSorted array is \n");
    //printArray(arr, arr_size);
    return 0;
}

After reading the code for some time I still can not say I understand the idea of counting the inversions. However, I can point out three things in it which seem incorrect to me.

First, I can't see where you call the sizein() function to initialize the n variable.

The second problem is the condition here:

    if(data[i>data[j]]){
        count+=q-i;
    }

You compare the index i to the value of a data item data[j] which looks strange. Even worse, if you were to sort an array of geometric figures or an array of songs it could be just impossible due to incompatibility of the types of data to be compared. What's even worse, even if comparison succeedes, as in the case of an int index and an int value in data[] ,the result of comparison is an int value 1 if comparison is satisfied or 0 otherwise. As a result this condition will resolve to

    if(data[0]){
        count+=q-i;
    }

or to

    if(data[1]){
        count+=q-i;
    }

which is obviously wrong.

The correct code looks like this:

    if (data[i] > data[j]) {
        count += q - i;
    }

The error would be more apparent if you left appropriate spacing between operators and their operands.

Yet another error lurks in the call to merge_sort() . First, you fill the data[] array with this loop:

for (i = 0; i < n; i ++) {
    scanf("%d", &data[i]);
}

Obviously, you fill an n -items array with data at indices from 0 through n-1 .

Then you call the merge-sorting routine:

merge_sort( data, 0, n);

which suggests the parameter p is the index of the first item or the part to be sorted and q is one-past-the last item. However, this disagrees with recursive calls:

    merge_sort( data, p, q);
    merge_sort( data, q+1, r);

Setting q as the ending index in the first call and q+1 as the starting index in the second suggests the ending index is inclusive , that is, it is the position of the last item in the segment to be sorted. Otherwise the two calls would leave the item data[q] unsorted. This also follows from internal loops, which continue while i <= q or whle l <= r etc.

So the initial call shouldn't be

merge_sort( data, 0, n);

but rather

merge_sort( data, 0, n-1);

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