簡體   English   中英

快速排序無限循環數值接收

[英]Quick Sort infinite loop Numerical Recipies

我正在嘗試將一些代碼從MATLAB導出到MEX文件(a.la C)。 對於我要導出的代碼段,我需要實現一種可以對2D數組排序的算法。 打開數字食譜的副本,我發現基於索引的排序。 我已經以一種簡單的方式用零索引實現了該功能,稍后將對其進行簡化。 當前的問題是,當我運行函數時,當傳遞某些隨機數集時它將進入無限循環。 例如集合:

0.8147,
0.9058,
0.127,
0.9134,
0.6324,
0.0975,
0.2785,
0.5469,
0.9575,
0.9649,
0.1576,
0.9706,
0.9572,
0.4854,
0.8003,
0.1419,
0.4218,
0.9157,
0.7922,
0.9595

這些數字都不重復。 下面是我用C代碼編寫的數值接收版本。 關於出什么問題有什么建議嗎? 我已經花了3個小時了。 該算法為行為良好的隨機數集提供適當的索引。

#define SWAP(a,b) itemp=(a);(a)=(b);(b)=itemp;
#define M 7
#define NSTACK 50

long* IndexSort(unsigned long int vectorLength, double* column)
{

unsigned long i, indxt, ir = vectorLength, itemp,j, k, l = 1;
int jstack = 0, *istack;
long *indx;
double a;

istack = (int*)malloc(NSTACK*sizeof(int));
//initalize output
indx = (long*)malloc(vectorLength*sizeof(long));

for (j = 0; j < vectorLength; j++)
{
    indx[j] = j;

}

// 
while (true)
{
    if (ir - l < M)
    {   
        for (j = l+1; j <= ir;j++)
        {
            indxt = indx[j-1];
            a = column[indxt];
            for (i = j-1; i >= 1; i--)
            {
                if (column[indx[i - 1]] <= a)
                {
                    break;
                }
                indx[i + 1 - 1] = indx[i - 1];
            }
            indx[i + 1 - 1] = indxt;
        }
        if (jstack == 0)
        {
            break;
        }
        ir = istack[jstack--];
        l = istack[jstack--];
    }
    else
    {   

        k = (l + ir) >> 1;

        SWAP(indx[k - 1], indx[l + 1 - 1])

        if (column[indx[l + 1 - 1]] > column[indx[ir - 1]]){
            SWAP(indx[l + 1 - 1], indx[ir - 1])
        }

        if (column[indx[l - 1]] > column[indx[ir - 1]]){
            SWAP(indx[l - 1], indx[ir - 1])
        }

        if (column[indx[l + 1 - 1]] > column[indx[l - 1]]){
            SWAP(indx[l + 1 - 1], indx[l - 1])
        }

        i = l + 1;
        j = ir;
        indxt = indx[l - 1];
        a = column[indxt];
        while (true)
        {
            do i++; while (column[indx[i - 1]] < a);
            do j--; while (column[indx[j - 1]] > a);
            if (j < i) break;
            SWAP(indx[i - 1], indx[j - 1])
        }
        indx[l - 1] = indx[j - 1];
        indx[j - 1] = indxt;
        jstack += 2;
        if (jstack > NSTACK) error("NSTACK too small for IndexSort");

        if (ir - i + 1 > j - 1){
            istack[jstack] = ir;
            istack[jstack - 1] = l;
            ir = j - 1;
        }

        else{
            istack[jstack] = j - 1;
            istack[jstack - 1] = l;
            l = i;
        }


    }
}
free(istack);
return indx;
}

編輯1:我將#defines添加到頂部。 針對第一批評論:

  • 該函數調用產生一個排序索引的數組。 我將采用這些值,並使用它們對2D數組進行排序。 抱歉,我應該對此更加清楚。
  • 至於當前無法使用的調試器。 從MEX包裝器中調用該函數。 我將編寫一個主要功能,以便對此進行調查。

編輯2:

  • 按建議移動了free命令,但仍未更改。
  • 更新問題陳述。 我在論壇上閱讀問題,大多數人都崩潰了。 我的問題實際上是一個無限循環,我不知道它在哪里啟動。

在此先感謝您的幫助,

如果目標是從給定數組中對索引進行排序,則以下使用C ++ 11的代碼應該可以完成以下工作: std::sort和lambdas:

C ++ 11示例

#include <algorithm>
#include <iostream>
#include <array>

long* IndexSort(unsigned long int vectorLength, double* column)
{
    long *index = new long[vectorLength](); // I really don't recommend this line
    long n = 0;
    std::generate( index, index + vectorLength, [&] { return n++; });
    std::sort(index, index + vectorLength, [&](long v1, long v2) 
             { return column[v1] < column[v2]; });
    return index;
}

using namespace std;

int main()
{  
  std::array<double,20> testData = 
                        {0.8147,0.9058,0.127,0.9134,0.6324,0.0975,0.2785,
                        0.5469,0.9575,0.9649,0.1576,0.9706,0.9572,0.4854,
                        0.8003,0.1419,0.4218,0.9157,0.7922,0.9595};
  long *indices = IndexSort(testData.size(), &testData[0]);
  for (size_t i = 0; i < testData.size(); ++i )
    cout << testData[indices[i]] << "  has an index of " << indices[i] << "\n";
  delete [] indices;
}

實時示例: http//ideone.com/EsOFKt

請注意,我們所做的只是建立一個排序的索引數組,並使用傳遞給lambda的兩個索引來比較原始的double向量。

注意,不必在索引的開頭分配內存,因為std::vector<long>是執行此操作的常用方法。 但是,我試圖模仿您返回動態分配的內存的指針的原始代碼要求。


C ++ 0x,98范例

如果使用的是C ++ 11之前的編譯器,則可以將代碼更改為此:

#include <algorithm>
#include <iostream>

struct IndexSorter
{
   double *m_array;
   IndexSorter(double *oArray) : m_array(oArray) {}
   bool operator()(long v1, long v2) const { return m_array[v1] < m_array[v2]; }
};

long* IndexSort(unsigned long int vectorLength, double* column)
{
    long *index = new long[vectorLength](); // I really don't recommend this line
    for (unsigned long i = 0; i < vectorLength; ++i) 
        index[i] = i;

    std::sort(index, index + vectorLength, IndexSorter(column));
    return index;
}

using namespace std;

int main()
{  
  double testData[] =   {0.8147,0.9058,0.127,0.9134,0.6324,0.0975,0.2785,
                        0.5469,0.9575,0.9649,0.1576,0.9706,0.9572,0.4854,
                        0.8003,0.1419,0.4218,0.9157,0.7922,0.9595};
  unsigned long testSize = sizeof(testData) / sizeof(testData[0]);
  long *indices = IndexSort(testSize, &testData[0]);
  for (unsigned long i = 0; i < testSize; ++i )
    cout << testData[indices[i]] << "  has an index of " << indices[i] << "\n";
  delete [] indices;
}

實時示例: http//ideone.com/nhMwSs


C示例

由於此問題也被標記為C ,因此這里是一個C實現:

#include <stdlib.h>
#include <stdio.h>

static double *myArray;

int compareIndices(const void* v1, const void *v2)
{
    long val1 = *(long *)v1;
    long val2 = *(long *)v2;
    if (myArray[val1] < myArray[val2])
        return -1;
    else
    if ( myArray[val1] > myArray[val2])
        return 1;
    return 0;
}

long* IndexSort(unsigned long int vectorLength, double* column)
{
    myArray = column;
    long *index = malloc(vectorLength * sizeof(long));
    if ( index )
    {
        unsigned long i;
        for (i = 0; i < vectorLength; ++i)
            index[i] = i;
        qsort(index, vectorLength, sizeof(long), compareIndices);
        return index;
    }
    return 0;
}

int main()
{
    double testData[] = { 0.8147, 0.9058, 0.127, 0.9134, 0.6324, 0.0975, 0.2785,
        0.5469, 0.9575, 0.9649, 0.1576, 0.9706, 0.9572, 0.4854,
        0.8003, 0.1419, 0.4218, 0.9157, 0.7922, 0.9595 };
    unsigned long numItems = sizeof(testData) / sizeof(testData[0]);
    long *indices = IndexSort(numItems, testData);
    if ( indices )
    {
        unsigned long i;
        for (i = 0; i < numItems; ++i)
            printf("%lf has an index of %ld\n", testData[indices[i]], indices[i]);
        free(indices);
    }
}

實時示例: http//ideone.com/8SZH1m

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM