优化qsort

时间:2015-03-12 20:11:16

标签: c algorithm sorting optimization qsort

我一直在寻找最快的算法来排序1,000,000个整数。到目前为止,令人惊讶的是,C内置的qsort函数似乎是我尝试的任何东西中最快的(我已经测试了预排序,反向排序和随机输入文件)。平均而言,我获得了大约.07秒的预先和反向排序和.2秒的随机。

如何优化它以更快地运行?有没有快速的技巧?我知道C ++的std排序更快,但不能在C中使用...我附上了我的代码。

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

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

1 个答案:

答案 0 :(得分:1)

此计数/基数排序将在我的系统(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);
}