使用qsort()进行稳定排序?

时间:2018-01-07 08:04:31

标签: c++ algorithm sorting

我试图解决在线评判系统中的问题:https://acm.cs.nthu.edu.tw/problem/11519/ 它需要一个整数n,后跟n行名称和等级。 问题是使用稳定的排序算法按等级对它们进行排序。 我使用qsort()并在compar()中给出person的顺序来稳定qsort()。这是我的代码:

class People{
    public:
        char name[11];
        int grade;
        int order;
        void print(){ printf("%s %d\n", name, grade); }
};

int compar(const void *a, const void *b){
    People *A = (People*)a;
    People *B = (People*)b;
    if(A->grade > B->grade) return 1;
    else if(A->grade < B->grade) return -1;
    else if(A->order > B->order) return 1;
    else if(A->order < B->order) return -1;
}

int main(){
    int n;
    scanf("%d", &n);
    People *p = new People[n];
    for(int i=0;i<n;i++){
        scanf("%s %d", p[i].name, &p[i].grade);
        p[i].order = i;
    }
    qsort(p, n, sizeof(People), compar);
    for(int i=0;i<n;i++){
        p[i].print();
    }
}

在我的所有测试用例中,它没有任何问题,但是在线评判一直给我提交四个WAs(错误答案)。有人可以给我一些线索吗?非常感谢!

2 个答案:

答案 0 :(得分:5)

比较函数中的 intent 实际上没有任何问题,它是使用原始排序将不稳定排序变为稳定排序的完全有效的解决方案。

那么,为什么它被拒绝,我无法确定,至少无法访问所使用的测试数据。

可能这些名称可能包含空格,这些空格会搞砸您的输入法,但(1)似乎没有被测试说明所指示; (2)它会使输入更加困难,至少在任务目标所针对的水平上是这样。

但是,尽管您可能认为不太可能,但 可能会使排序算法在某个时刻将对象与自身进行比较。这意味着它将返回一些任意值,因为假设它们总是不同的,给定添加的order检查。

您应该可以满足这一要求,因为您在比较函数中要遵循的一条规则是一致性,如果a > bb < a。所以,两个规则,确实: - )

此外,我 建议的一件事是尽可能减少对{C}提供更好设施的printfscanf等遗留C的使用。

为此,我相信你会更好:

#include <iostream>
#include <cstdlib>

struct People {
    char name[11];
    int grade;
    int order;
    void print() { std::cout << name << " " << grade << std::endl; }
};

int compar(const void *a, const void *b) {
    People *A = (People*)a;
    People *B = (People*)b;

    // Use grade if different.

    if (A->grade > B->grade) return 1;
    if (A->grade < B->grade) return -1;

    // Otherwise, use order, unique in different objects.

    if (A->order > B->order) return 1;
    if (A->order < B->order) return -1;

    // But cater for the possibility you may compare an object with itself.

    return 0;
}

int main() {
    int n;
    std::cin >> n;

    People *p = new People[n];

    for (int i = 0; i < n; i++) {
        std::cin >> p[i].name >> p[i].grade;
        p[i].order = i;
    }

    qsort(p, n, sizeof(People), compar);

    for (int i = 0; i < n; i++) {
        p[i].print();
    }
}

您甚至可能还想考虑远离遗留C qsort,因为C ++提供了内置的稳定排序,特别是stable_sort中的<algorithm>

答案 1 :(得分:0)

最终我错过了描述中的一行:

  

输入包括多个测试用例。在每个测试用例中,第一行包含一个整数N。

经过多次处理后,我通过以下代码传递了它:

class People{
    public:
        char name[11];
        int grade;
        int order;
        void print(){
            printf("%s %d\n", name, grade);
        }
};

int compar(const void *a, const void *b){
    People *A = (People*)a;
    People *B = (People*)b;
    if(A->grade > B->grade) return 1;
    else if(A->grade < B->grade) return -1;
    else if(A->order > B->order) return 1;
    else if(A->order < B->order) return -1;
    return 0;
}

int main(){
    int n;
    while(scanf("%d", &n)!=EOF){
        People *p = new People[n];
        for(int i=0;i<n;i++){
            scanf("%s %d", p[i].name, &p[i].grade);
            p[i].order = i;
        }
        qsort(p, n, sizeof(People), compar);
        for(int i=0;i<n;i++){
            p[i].print();
        }
        delete[] p;
    }
}

std :: stable_sort正常工作,然而,它收到TLE(超出时间限制),而cin / cout也会导致TLE。所以这就是我坚持使用printf / scanf的原因。

感谢大家回答这个问题! :)