簡體   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