【问题标题】:How to sort a struct of a pair of integers using quicksort?如何使用快速排序对一对整数的结构进行排序?
【发布时间】:2017-02-04 14:37:34
【问题描述】:

假设我有以下结构:

struct Pair {
    int x;
    int y;
}

我想按对中的第一个元素(即 x)对数组进行排序,然后按第二个元素对数组进行排序,因此如果我们得到以下内容:

input:  [(1,2), (1,0), (2,3), (1,4), (2,2)]
output: [(1,0), (1,2), (1,4), (2,2), (2,3)]

现在我有两个函数,其中一个按第一个元素对数组进行排序,第二个按第二个元素对数组进行排序,但效率较低。如何遍历数组一次并达到预期的结果?

void sort1(Pair ps[], int size) {
    int i, j;

    for (i = 0; i < size; i++) {
        for (j = i + 1; j < size; j++) {
            if (ps[j].x > ps[j+1].x) {
                Pair temp = ps[j+1];
                ps[j+1] = ps[j];
                ps[j] = temp;
            }
        }
    }
}

void sort2(Pair ps[], int size) {
    int i, j;

    for (i = 0; i < size; i++) {
        for (j = i + 1; j < size; j++) {
            if (ps[j].y > ps[j+1].y) {
                Pair temp = ps[j+1];
                ps[j+1] = ps[j];
                ps[j] = temp;
            }
        }
    }
}

另外,有没有一种使用内置排序功能的快速方法?

【问题讨论】:

  • 但是c中有内置函数吗?在 C++ 中这是可能的。
  • 这个问题没有显示任何研究工作。
  • 对我来说,您的排序功能不是快速排序,即使您只有单个值要排序,也不会正确排序。但要解决先排序 x 和后排序 y 的问题,您需要添加 "else if(ps[j]x == ps[j+1].x) { if (ps[j].y > ps[j+ 1].y { Pair temp = ps[j+1]; ps[j+1] = ps[j]; ps[j] = temp;}}. 除非你想学习如何实现快速排序算法,c stdlib 中已经有一个快速排序函数。输入 man qsort。
  • @Shiping 您提议的else if 正文与现有的if 正文相同,因此您不需要else;你可以合并条件。 qsort 使用未指定的排序算法;它不必是快速排序。 OP 的代码是冒泡排序。
  • 冒泡排序虽然稳定,但是太慢了。特别是因为您使用了两个排序功能。

标签: c arrays sorting struct lexicographic


【解决方案1】:

您可以使用qsort(),它是快速排序的 C 库实现。

为了使用这个函数,你需要设计一个cmp函数来比较两个x的值,如果它们是相同的,则按y排序。

为了不把它弄乱成一个cmp函数,你可以先做一个更小的函数来测试两个整数的相等性:

int compare_int(const int a , const int b) {
    if (a < b) {
        return -1;
    } else if (a > b) {
        return 1;
    }
    return 0;
}

然后您可以将其集成到您的主要cmp 函数中,qsort() 将调用该函数。这个函数可以很简单:

int cmp_func(const void *a, const void *b) {
    const pair_t *num1 = (pair_t *)a;
    const pair_t *num2 = (pair_t *)b;

    if (num1->x == num2->x) {
        return compare_int(num1->y, num2->y);
    } else if (num1->x > num2->x) {
        return +1;
    }
    return -1;
}

然后你可以简单地调用qsort()如下:

qsort(ps, sizeof(ps)/sizeof(ps[0]), sizeof(pair_t), cmp_func);

下面是一些执行此操作的示例代码:

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

#define ARRAYSIZE(x) ((sizeof(x))/sizeof(x[0])) 

typedef struct {
    int x;
    int y;
} pair_t;

int compare_int(const int a , const int b) {
    if ( a < b ) {
        return -1;
    } else if ( a > b ) {
        return 1;
    }
    return 0;
}

int cmp_func(const void *a, const void *b) {
    const pair_t *num1 = (pair_t *)a;
    const pair_t *num2 = (pair_t *)b;

    if (num1->x == num2->x) {
        return compare_int(num1->y, num2->y);
    } else if (num1->x > num2->x) {
        return +1;
    }
    return -1;
}

void print_array(pair_t ps[], size_t n) {
    printf("[");
    for (size_t i = 0; i < n; i++) {
        printf("(%d,%d)", ps[i].x, ps[i].y);
        if (i != n-1) {
            printf(", ");
        }
    }
    printf("]\n");
}  

int main(void) {
    pair_t ps[] = {{1,2}, {1,0}, {2,3}, {1,4}, {2,2}};

    printf("Input: ");
    print_array(ps, ARRAYSIZE(ps));

    qsort(ps, ARRAYSIZE(ps), sizeof(pair_t), cmp_func);

    printf("Output: ");
    print_array(ps, ARRAYSIZE(ps));

    return 0;
}

哪些输出:

Input: [(1,2), (1,0), (2,3), (1,4), (2,2)]
Output: [(1,0), (1,2), (1,4), (2,2), (2,3)]

注意:您实现冒泡排序的原始代码平均有 O(n^2) 运行时间。但是,如果您改用 qsort(),您将能够实现更快的平均 O(logN) 运行时间。如果n 变大,这种差异将有助于更快地获得结果。

【讨论】:

  • 这很整洁。你能解释一下为什么在qsort(ps, ARRAYSIZE(ps), sizeof(pair_t), cmp_func); 函数 cmp_func 不接受任何输入吗?
  • @user6005857 看看void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))compar 是一个函数指针,因此只需调用它的名称就足够了。具体来说,cmp_func 是函数指针,*cmp_func 是函数。您可以阅读this 了解有关函数指针的更多信息。起初它们有点奇怪,但有时会很方便。
  • @user6005857 cmp_func(...) 是一个函数调用。 qsort(..., cmp_func(...)) 将把调用cmp_func 的结果传递给qsort。但这里我们正在做qsort(..., cmp_func),它将cmp_func 函数本身传递给qsort;我们不叫它。这让qsort 调用cmp_func 本身,可能多次,使用不同的参数。
【解决方案2】:

你只需要一个适当的函数来比较两对:

int comparePairs (const void * a, const void * b)
{
  const Pair* A = (const Pair*) a;
  const Pair* B = (const Pair*) b;
  return (A.x == B.x) ? (A.y - B.y) : (A.x - B.x);
}

那么就可以使用内置函数qsort了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2019-07-13
    • 2016-07-07
    相关资源
    最近更新 更多