繁体   English   中英

稳定标准库 qsort?

[英]Stabilizing the standard library qsort?

我假设 stdlib 中的旧 qsort function 不稳定,因为手册页没有说明任何内容。 这就是我说的 function:

   #include <stdlib.h>
   void qsort(void *base, size_t nmemb, size_t size,
              int(*compar)(const void *, const void *));  

我假设如果我将比较 function 更改为还包括我正在比较的地址,它将是稳定的。 那是对的吗?

例如:

int compareFoos( const void* pA, const void *pB ) {
    Foo *pFooA = (Foo*) pA;
    Foo *pFooB = (Foo*) pB;

    if( pFooA->id < pFooB->id ) {
        return -1;
    } else if( pFooA->id > pFooB->id ) {
        return 1;
    } else if( pA < pB ) {
        return -1;            
    } else if( pB > pA ) {
       return 1;
    } else {
       return 0;
    }
}   

不,不幸的是,你不能依赖它。 假设您有数组(每条记录中的两个字段用于检查,但只有第一个字段用于排序):

BBBB,1
BBBB,2
AAAA,3

快速排序可以将 BBBB,1 与 AAAA,3 进行比较并交换它们,给出:

AAAA,3
BBBB,2
BBBB,1

如果下一步是将 BBBB,2 与 BBBB,1 进行比较,则密钥将相同,并且由于 BBBB,2 的地址小于 BBBB,1,因此不会发生交换。 对于稳定的排序,您应该最终得到:

AAAA,3
BBBB,1
BBBB,2

唯一的方法是附加指针的起始地址(不是它的当前地址)并使用它以及其他键进行排序。 这样,原始地址将成为排序键的次要部分,因此无论排序过程中两条BBBB行 go 位于何处, BBBB,1最终都会在BBBB,2之前结束。

规范的解决方案是制作(即分配 memory 并填充)指向原始数组元素的指针数组,并对这个新数组进行qsort ,使用额外的间接级别并回退到比较指针时他们指向的东西是平等的。 这种方法具有潜在的附带好处,即您根本不修改原始数组 - 但如果您希望原始数组最终排序,则必须对其进行置换以匹配指针数组中的顺序qsort返回。

这不起作用,因为在排序过程中,排序将发生变化,两个元素的 output 将不一致。 为了使老式的 qsort 稳定,我所做的是在我的结构中添加初始索引并在将其传递给 qsort 之前初始化该值。

typedef struct __bundle {
    data_t some_data;
    int sort_score;
    size_t init_idx;
} bundle_t;

/*
 .
 .
 .
 .
*/

int bundle_cmp(void *ptr1, void *ptr2) {
    bundle_t *b1, *b2;
    b1 = (budnel_t *) ptr1;
    b2 = (budnel_t *) ptr2;
    if (b1->sort_score < b2->sort_score) {
        return -1;
    }
    if (b1->sort_score > b2->sort_score) {
        return 1;
    }
    if (b1->init_idx < b2->init_idx) {
        return -1;
    }
    if (b1->init_idx > b2->init_idx) {
        return 1;
    }
    return 0;
}

void sort_bundle_arr(bundle_t *b, size_t sz) {
    size_t i;
    for (i = 0; i < sz; i++) {
        b[i]->init_idx = i;
    }
    qsort(b, sz, sizeof(bundle_t), bundle_cmp);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM