优化排序

Optimizing qsort

我一直在寻找最快的算法来对 1,000,000 个整数进行排序。到目前为止,令人惊讶的是,C 的内置 qsort 函数似乎是我尝试过的所有函数中最快的(我已经测试了预排序、反向排序和随机输入文件)。平均而言,前后排序大约需要 0.07 秒,随机大约需要 0.2 秒。

如何将其优化为 运行 更快?有什么快速的技巧吗?我知道 C++ 的 std 排序更快,但是不能在 C 中使用...我附上了我的代码。

int compare(const void *x, const void *y){   
   return ( *(int*)x >= *(int*)y );
}

qsort(list, 1000000, sizeof(int), compare);

在我的系统(Intel 2600K 3.4ghz)上,这种计数/基数排序将在大约 0.01 秒内对 1,000,000 个 32 位无符号整数进行排序,但它使用与原始数组 (pData) 大小相同的第二个数组 (pTemp) ), 所以它需要两倍的内存。

typedef unsigned int UI32;

UI32 * RadixSort(UI32 * pData, UI32 * pTemp, size_t count)
{
size_t mIndex[4][256] = {0};            // index matrix
UI32 *pDst, *pSrc, *pTmp;
size_t i,j,m,n;
UI32 u;

    for(i = 0; i < count; i++){         // generate histograms
        u = pData[i];
        for(j = 0; j < 4; j++){
            mIndex[j][(size_t)(u & 0xff)]++;
            u >>= 8;
        }       
    }
    for(j = 0; j < 4; j++){             // convert to indices
        n = 0;
        for(i = 0; i < 256; i++){
            m = mIndex[j][i];
            mIndex[j][i] = n;
            n += m;
        }       
    }
    pDst = pTemp;                       // radix sort
    pSrc = pData;
    for(j = 0; j < 4; j++){
        for(i = 0; i < count; i++){
            u = pSrc[i];
            m = (size_t)(u >> (j<<3)) & 0xff;
            pDst[mIndex[j][m]++] = u;
        }
        pTmp = pSrc;
        pSrc = pDst;
        pDst = pTmp;
    }
    return(pSrc);
}

对于有符号整数,用于索引时只需要补整数的符号位即可:

typedef          int  I32;
typedef unsigned int UI32;

I32 * RadixSort(I32 * pData, I32 * pTemp, size_t count)
{
size_t mIndex[4][256] = {0};            // index matrix
UI32 *pDst, *pSrc, *pTmp;
size_t i,j,m,n;
UI32 u;

    for(i = 0; i < count; i++){         // generate histograms
        u = pData[i];
        for(j = 0; j < 4; j++){
            if(j != 3)                  //  signed integer handling
                mIndex[j][(size_t)(u & 0xff)]++;
            else
                mIndex[j][(size_t)((u^0x80) & 0xff)]++;
            u >>= 8;
        }       
    }
    for(j = 0; j < 4; j++){             // convert to indices
        n = 0;
        for(i = 0; i < 256; i++){
            m = mIndex[j][i];
            mIndex[j][i] = n;
            n += m;
        }       
    }
    pDst = (UI32 *)pTemp;               // radix sort
    pSrc = (UI32 *)pData;
    for(j = 0; j < 4; j++){
        for(i = 0; i < count; i++){
            u = pSrc[i];
            if(j != 3)                  //  signed integer handling
                m = (size_t)(u >> (j<<3)) & 0xff;
            else
                m = (size_t)((u >> (j<<3))^0x80) & 0xff;
            pDst[mIndex[j][m]++] = u;
        }
        pTmp = pSrc;
        pSrc = pDst;
        pDst = pTmp;
    }
    return((I32 *)pSrc);
}