qsort не работает должным образом с длинным длинным
Я сортирую двумерный массив a[n][2] по отношению к a[i][0],a[i+1][0], разрывая связи с неубывающими a [i] [1], a [+1][1]. qsort работает нормально с целочисленным массивом, но не с длинным длинным массивом.
Код целочисленного массива
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
int cmpfunc(const void* a, const void* b)
{
int x = ((int*)a)[0] - ((int*)b)[0];
if (x != 0) {
return x;
}
return ((int*)a)[1] - ((int*)b)[1];
}
int main(int argc, char const* argv[])
{
int n, i, j;
scanf("%d", &n);
int a[n][2];
for (i = 0; i < n; i = i + 1) {
scanf("%d %d", &a[i][0], &a[i][1]);
}
qsort(a, n, sizeof(a[0]), cmpfunc);
for (i = 0; i < n; i = i + 1) {
printf("%d %d\n", a[i][0], a[i][1]);
}
return 0;
}
длинный длинный код массива
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
int cmpfunc(const void* a, const void* b)
{
int x = ((int*)a)[0] - ((int*)b)[0];
if (x != 0) {
return x;
}
return ((int*)a)[1] - ((int*)b)[1];
}
int main(int argc, char const* argv[])
{
int n, i, j;
scanf("%d", &n);
long long a[n][2];
for (i = 0; i < n; i = i + 1) {
scanf("%I64d %I64d", &a[i][0], &a[i][1]);
}
qsort(a, n, sizeof(a[0]), cmpfunc);
for (i = 0; i < n; i = i + 1) {
printf("%I64d %I64d\n", a[i][0], a[i][1]);
}
return 0;
}
Входные данные:
5
4 3
4 2
4 1
4 1
4 1
Выход для первого кода:
4 1
4 1
4 1
4 2
4 3
Выход для второго кода:
4 2
4 1
4 1
4 1
4 3
3 ответа
На самом деле у вас есть две проблемы: первая - это проблема с неверным приведением. Второй также о недопустимом кастинге, но по другой причине.
Как указано в одном из моих комментариев qsort
Функция передает указатели на элементы в функцию сравнения. Если у вас есть массив arr
затем qsort
будет использовать что-то вроде &arr[0]
для аргументов. Это означает, что если данные массива сами являются массивами, то аргументы будут указателями на массивы. В вашем конкретном случае типы аргументов действительно long long (*)[2]
, не только long long *
,
Поэтому функция сравнения должна выглядеть примерно так:
int cmpfunc(const void* a_, const void* b_)
{
long long (*a)[2] = (long long (*)[2]) a_;
long long (*b)[2] = (long long (*)[2]) b_;
long long result;
if ((*a)[0] - (*b)[0] != 0)
result = (*a)[0] - (*b)[0];
else
result = (*a)[1] - (*b)[1];
if (result < 0)
return -1;
else if (result > 0)
return 1;
else
return 0;
}
Вы все еще брошены на int *
в вашей функции сравнения, даже если вы изменили тип данных на long long
,
Если вы включили предупреждение во время компиляции (-Wall -pedantic
для GCC) вы должны заметить, что вам нужен другой заполнитель для long long int
и вы не можете предположить, что это 64-bit
, Вы также неверно приводите аргументы функции сравнения. Обратите внимание, что разница между двумя long long int
может быть за пределами диапазона int
так что вы не можете использовать это (тот, который я написал) qsort()
сравнить реализацию. Вот код:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
int cmpfunc(const void *a,const void *b){
long long int x=((long long int *)a)[0]-((long long int *)b)[0];
if(x!=0){
return x;
}
return ((long long int *)a)[1]-((long long int *)b)[1];
}
int main(int argc, char const *argv[]){
int n,i;
scanf("%d",&n);
long long a[n][2];
for(i=0;i<n;i=i+1){
scanf("%lld %lld",&a[i][0],&a[i][1]);
}
qsort(a,n,sizeof(a[0]),cmpfunc);
for(i=0;i<n;i=i+1){
printf("%lld %lld\n",a[i][0],a[i][1]);
}
return 0;
}