如何为二维数组的 qsort 编写比较器函数?
How to write a comparator function for qsort for a 2D array?
我有一个 n*2 大小的数组。我想根据第 2 列的值使用 qsort 对它们进行排序。
#include<stdio.h>
int cmp(const int **a, const int **b) {
//return 0;
//return *a[1] - *b[1]
// return *a - *b;
}
int main()
{
int t; // test cases
scanf("%d", &t);
for(int i=0; i<t; i++) {
int n;
scanf("%d", &n); // size of array
int **arr = (int **)malloc(n * sizeof(int *));
for(int j =0; j< n; j++) {
arr[j] = (int *) malloc(2*sizeof(int));
}
for(int j =0; j< 2; j++) {
for(int k =0; k< n; k++) {
scanf("%d", &arr[k][j]);
}
}
for(int k =0; k< n; k++) {
for(int j =0; j<= 1; j++) {
printf("%d\t", arr[k][j]);
}
printf("\n");
}
// qsort(arr, n, sizeof(arr[0]), cmp);
}
return 0;
}
所以对于输入,
1 2
3 6
0 8
5 4
8 9
5 7
输出是,
1 2
5 4
3 6
5 7
0 8
8 9
我试过了,但无法根据第 2 列对它们进行排序。我对将数组元素传递给比较器感到困惑。还要传递什么作为元素的大小?但我猜下面的前两个是正确的。
qsort(arr, n, sizeof(arr[0]), cmp);
//qsort(arr, n, sizeof((int *)), cmp);
//qsort(arr, n, 2 * sizeof((int)), cmp);
我尝试了比较器的各种组合。
请指点或解释。
比较函数的原型在qsort
函数的原型中指定:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
你的比较函数必须是兼容的,所以你可以这样定义它:
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int *aa = *(int * const *)a;
int *bb = *(int * const *)b;
return (aa[1] > bb[1]) - (aa[1] < bb[1]);
}
或没有演员表:
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int * const *aa = a;
int * const *bb = b;
int ia = (*aa)[1];
int ib = (*bb)[1];
return (ia > ib) - (ia < ib);
}
请注意,您不能使用简单的比较 aa[1] - bb[1]
,因为它可能会溢出较大的值,最多只能产生不正确的输出。
此外,您输入的循环不正确:您应该以相反的顺序嵌套循环:
for (int k = 0; k < n; k++) {
for (int j = 0; j < 2; j++) {
scanf("%d", &arr[k][j]);
}
}
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int * const *aa = a;
int * const *bb = b;
int ia = (*aa)[1];
int ib = (*bb)[1];
return (ia > ib) - (ia < ib);
}
int main() {
int t; // test cases
scanf("%d", &t);
for (int i = 0; i < t; i++) {
int n;
scanf("%d", &n); // size of array
int **arr = malloc(sizeof(*arr) * n);
for (int j = 0; j < n; j++) {
arr[j] = malloc(sizeof(*arr[j]) * 2);
}
for (int k = 0; k < n; k++) {
for (int j = 0; j < 2; j++) {
scanf("%d", &arr[k][j]);
}
}
qsort(arr, n, sizeof(arr[0]), cmp);
for (int k = 0; k < n; k++) {
for(int j = 0; j < 2; j++) {
printf("%d\t", arr[k][j]);
}
printf("\n");
}
for (int j = 0; j < n; j++) {
free(arr[j]);
}
free(arr);
}
return 0;
}
您还可以使用实际的二维数组来简化代码:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
const int *aa = a;
const int *bb = b;
return (aa[1] > bb[1]) - (aa[1] < bb[1]);
}
int main() {
int t; // test cases
scanf("%d", &t);
for (int i = 0; i < t; i++) {
int n;
scanf("%d", &n); // size of array
int (*arr)[2] = malloc(sizeof(*arr) * n);
for (int k = 0; k < n; k++) {
scanf("%d%d", &arr[k][0], &arr[k][1]);
}
qsort(arr, n, sizeof(arr[0]), cmp);
for (int k = 0; k < n; k++) {
printf("%d\t%d\n", arr[k][0], arr[k][1]);
}
free(arr);
}
return 0;
}
首先你没有二维数组。您有一个一维指针数组,每个指针都指向一个 int
.
的一维数组
所以你可以做的是对一维指针数组进行排序。为此,您可以编写一个比较函数来查看指向元素的值。
它可能看起来像:
int cmp(const void * a, const void * b)
{
int* const * x = a;
int* const * y = b;
if ((*x)[1] < (*y)[1]) return -1;
if ((*x)[1] > (*y)[1]) return 1;
return 0;
}
如上所说:排序的是指针数组。您可以将其可视化为:
我有一个 n*2 大小的数组。我想根据第 2 列的值使用 qsort 对它们进行排序。
#include<stdio.h>
int cmp(const int **a, const int **b) {
//return 0;
//return *a[1] - *b[1]
// return *a - *b;
}
int main()
{
int t; // test cases
scanf("%d", &t);
for(int i=0; i<t; i++) {
int n;
scanf("%d", &n); // size of array
int **arr = (int **)malloc(n * sizeof(int *));
for(int j =0; j< n; j++) {
arr[j] = (int *) malloc(2*sizeof(int));
}
for(int j =0; j< 2; j++) {
for(int k =0; k< n; k++) {
scanf("%d", &arr[k][j]);
}
}
for(int k =0; k< n; k++) {
for(int j =0; j<= 1; j++) {
printf("%d\t", arr[k][j]);
}
printf("\n");
}
// qsort(arr, n, sizeof(arr[0]), cmp);
}
return 0;
}
所以对于输入,
1 2
3 6
0 8
5 4
8 9
5 7
输出是,
1 2
5 4
3 6
5 7
0 8
8 9
我试过了,但无法根据第 2 列对它们进行排序。我对将数组元素传递给比较器感到困惑。还要传递什么作为元素的大小?但我猜下面的前两个是正确的。
qsort(arr, n, sizeof(arr[0]), cmp);
//qsort(arr, n, sizeof((int *)), cmp);
//qsort(arr, n, 2 * sizeof((int)), cmp);
我尝试了比较器的各种组合。
请指点或解释。
比较函数的原型在qsort
函数的原型中指定:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
你的比较函数必须是兼容的,所以你可以这样定义它:
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int *aa = *(int * const *)a;
int *bb = *(int * const *)b;
return (aa[1] > bb[1]) - (aa[1] < bb[1]);
}
或没有演员表:
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int * const *aa = a;
int * const *bb = b;
int ia = (*aa)[1];
int ib = (*bb)[1];
return (ia > ib) - (ia < ib);
}
请注意,您不能使用简单的比较 aa[1] - bb[1]
,因为它可能会溢出较大的值,最多只能产生不正确的输出。
此外,您输入的循环不正确:您应该以相反的顺序嵌套循环:
for (int k = 0; k < n; k++) {
for (int j = 0; j < 2; j++) {
scanf("%d", &arr[k][j]);
}
}
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
/* a and b are pointers to the array of pointers. */
int * const *aa = a;
int * const *bb = b;
int ia = (*aa)[1];
int ib = (*bb)[1];
return (ia > ib) - (ia < ib);
}
int main() {
int t; // test cases
scanf("%d", &t);
for (int i = 0; i < t; i++) {
int n;
scanf("%d", &n); // size of array
int **arr = malloc(sizeof(*arr) * n);
for (int j = 0; j < n; j++) {
arr[j] = malloc(sizeof(*arr[j]) * 2);
}
for (int k = 0; k < n; k++) {
for (int j = 0; j < 2; j++) {
scanf("%d", &arr[k][j]);
}
}
qsort(arr, n, sizeof(arr[0]), cmp);
for (int k = 0; k < n; k++) {
for(int j = 0; j < 2; j++) {
printf("%d\t", arr[k][j]);
}
printf("\n");
}
for (int j = 0; j < n; j++) {
free(arr[j]);
}
free(arr);
}
return 0;
}
您还可以使用实际的二维数组来简化代码:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
const int *aa = a;
const int *bb = b;
return (aa[1] > bb[1]) - (aa[1] < bb[1]);
}
int main() {
int t; // test cases
scanf("%d", &t);
for (int i = 0; i < t; i++) {
int n;
scanf("%d", &n); // size of array
int (*arr)[2] = malloc(sizeof(*arr) * n);
for (int k = 0; k < n; k++) {
scanf("%d%d", &arr[k][0], &arr[k][1]);
}
qsort(arr, n, sizeof(arr[0]), cmp);
for (int k = 0; k < n; k++) {
printf("%d\t%d\n", arr[k][0], arr[k][1]);
}
free(arr);
}
return 0;
}
首先你没有二维数组。您有一个一维指针数组,每个指针都指向一个 int
.
所以你可以做的是对一维指针数组进行排序。为此,您可以编写一个比较函数来查看指向元素的值。
它可能看起来像:
int cmp(const void * a, const void * b)
{
int* const * x = a;
int* const * y = b;
if ((*x)[1] < (*y)[1]) return -1;
if ((*x)[1] > (*y)[1]) return 1;
return 0;
}
如上所说:排序的是指针数组。您可以将其可视化为: