短阵列的最佳排序功能

时间:2012-03-15 13:48:47

标签: c arrays sorting

我正在研究一种操纵图片的算法。 基本上我将实现扩散(每个像素将获得8个周围像素的中值+它自己的值)。

我要做的是用值创建一个包含9个整数的数组,对数组进行排序并获得数组[4]的中值。

我仍然不知道该问题的用途是什么,对于相对较小的数组使用的最佳排序函数是什么?排序功能大致称为x次,x是像素数。

Heapsort似乎有点矫枉过正。 Quicksort表现不佳。而且我不想实施非常复杂的事情。

你们觉得怎么样?

3 个答案:

答案 0 :(得分:17)

如果您只需要中位数,则根本不需要进行任何排序! (对于长数组,请参阅http://en.wikipedia.org/wiki/Selection_algorithm了解O(n)算法;当然我们这里只讨论短数组。)

对于9个数字的中位数,有点谷歌搜索显示N.Devillard撰写的文章Fast median search: an ANSI C implementation,它指的是JL Smith撰写的文章在XC4000E FPGA中实现中值滤波器不言自明的“排序网络”,通过19次比较获得中位数:

enter image description here

就C而言:

typedef int T;

void sort2(T* a, T* b);
void sort3(T* a, T* b, T* c);
T min3(T a, T b, T c);
T max3(T a, T b, T c);

T median9(T p1, T p2, T p3, T p4, T p5, T p6, T p7, T p8, T p9)
{
    sort3(&p1, &p2, &p3);
    sort3(&p4, &p5, &p6);
    sort3(&p7, &p8, &p9);

    p7 = max3(p1, p4, p7);
    p3 = min3(p3, p6, p9);

    sort3(&p2, &p5, &p8);
    sort3(&p3, &p5, &p7);

    return p5;
}

void sort2(T* a, T* b)
{
    if (*a > *b)
    {
        T tmp = *b;
        *b = *a;
        *a = tmp;
    }
}

void sort3(T* a, T* b, T* c)
{
    sort2(b, c);
    sort2(a, b);
    sort2(b, c);
}

T min3(T a, T b, T c)
{
    if (a < b)
        return a < c ? a : c;
    else
        return b < c ? b : c;
}

T max3(T a, T b, T c)
{
    if (a > b)
        return a > c ? a : c;
    else
        return b > c ? b : c;
}

编辑:this file还包含获取3个,5个,6个,7个,9个和25个数字的中位数的代码。

#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
#define PIX_SWAP(a,b) { pixelvalue temp=(a);(a)=(b);(b)=temp; }

/*----------------------------------------------------------------------------
   Function :   opt_med9()
   In       :   pointer to an array of 9 pixelvalues
   Out      :   a pixelvalue
   Job      :   optimized search of the median of 9 pixelvalues
   Notice   :   in theory, cannot go faster without assumptions on the
                signal.
                Formula from:
                XILINX XCELL magazine, vol. 23 by John L. Smith

                The input array is modified in the process
                The result array is guaranteed to contain the median
                value
                in middle position, but other elements are NOT sorted.
 ---------------------------------------------------------------------------*/

pixelvalue opt_med9(pixelvalue * p)
{
    PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
    PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ;
    PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
    PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ;
    PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ;
    PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ;
    PIX_SORT(p[4], p[2]) ; return(p[4]) ;
}

答案 1 :(得分:2)

你知道c库的“标准”qsort通常是非常优化的吗?通常它是小型子阵列的快速排序+插入排序(当您细分基础阵列时)。例如,此版本的read the comments取自gnu c库

答案 2 :(得分:1)

从理论上讲,你想找到一个中位数,这是一个selection problem的特例。它可以在线性时间内完成。

但这是理论上的。实际上,我使用“基于分区的通用选择算法”(在文章中提到)。它平均在线性时间内工作,而且实际上简单快速。

template <typename T>
T* SubDivide(T* pB, T* pE)
{
    ASSERT(pB < pE);

    T* pPivot = --pE;
    const T pivot = *pPivot;

    while (pB < pE)
    {
        if (*pB > pivot)
        {
            --pE;
            std::swap(*pB, *pE);
        } else
            ++pB;
    }

    std::swap(*pE, *pPivot);
    return pE;
}

template <typename T>
void SelectElement(T* pB, T* pE, size_t k)
{
    ASSERT((pE > pB) && (k < unsigned(pE - pB)));

    while (true)
    {
        T* pPivot = SubDivide(pB, pE);
        size_t n = pPivot - pB;

        if (n == k)
            break;

        if (n > k)
            pE = pPivot;
        else
        {
            pB = pPivot + 1;
            k -= (n + 1);
        }
    }
}

// Usage example
int pArr[9] = { /* fill with values*/ };

// Select the 4th element (which is a median)
SelectElement(pArr, pArr + 9, 4);

// pArr[4] now holds the median value