2016-11-26 84 views
0

我試圖實現一種算法,它使用長度爲n的數組對長度的數組r進行排序。我沒有看到我的代碼錯在哪裏。我沒有得到預期的結果。結果應該看起來像一個填充莫頓曲線的空間。但正如你所看到的,結果包含很多零。我不知道他們來自哪裏?你能幫我找到錯誤嗎?這裏是我的可執行代碼:使用其他數組排序數組

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

#define DIM 2 

// Sort list "r" using list "mInt" 
void sort(unsigned int *mInt, double *r, int n){ 
    unsigned int i, j, ph0; 
    double ph1, ph2; 

    for(i = 1; i <= n-1; i++) 
     for(j = 1; j <= n-i; j++) 
     if(mInt[j-1] >= mInt[j]) 
     { 
      // 1 
      ph1 = r[DIM*(j-1)+0]; 
      ph2 = r[DIM*(j-1)+1]; 
      ph0 = mInt[j-1]; 

      // 2 
      mInt[j-1] = mInt[j]; 
      r[DIM*(j-1)+0] = r[DIM*j+0]; 
      r[DIM*(j-1)+1] = r[DIM*j+1]; 

      // 3 
      mInt[j] = ph0; 
      r[DIM*j+0] = ph1; 
      r[DIM*j+1] = ph2; 
     } 
} 

// Create morton key 
inline unsigned int mortoncode(unsigned int x, unsigned int y){ 
    int answer = 0; 
    for (unsigned int i = 0; i < (sizeof(unsigned int)* 8)/2; ++i) { 
     answer |= (((x & ((unsigned int)1 << i)) << 2*i) | ((y & ((unsigned int)1 << i)) << (2*i + 1))); 
    } 
    return answer; 
} 

// Find max/min values 
double maxValue(double *r, int n, int d){ 
    double max = r[d]; 
    for(int k=0; k<n; k++){ 
     if(max < r[DIM*k+d]){ 
      max = r[DIM*k+d]; 
     } 
    } 
    return max; 
} 
double minValue(double *r, int n, int d){ 
    double min = r[d]; 
    for(int k=0; k<n; k++){ 
     if(min > r[DIM*k+d]){ 
      min = r[DIM*k+d]; 
     } 
    } 
    return min; 
} 

int main(int argc, char **argv){ 
    FILE *f = fopen("data.dat", "w"); 
    int n = 100; 
    double r[n*DIM]; 

    // Initialize data 
    double x1 = 0; 
    double y1 = 0; 
    for(int k=0; k<n; k++){ 
     r[DIM*k+0] = x1; 
     r[DIM*k+1] = y1; 
     x1 += 0.1; 
     if(k % 10 == 0){ 
      y1 += 0.1; 
      x1 = 0; 
     } 
     printf("%lf %lf\n", r[DIM*k+0], r[DIM*k+1]); 
    } 

    // Get max/min values 
    double rMin[DIM]; 
    double rMax[DIM]; 
    for(int d=0; d<DIM; d++){ 
     rMin[d] = minValue(r, n, d); 
     rMax[d] = maxValue(r, n, d); 
    } 

    // Convert double data to integers 
    printf("\n"); 
    unsigned int rInt[n]; 
    for(int k=0; k<n; k++){ 
     for(int d=0; d<DIM; d++){ 
      int idx=DIM*k+d; 
      double map = floor(((2097151)/(rMax[d]-rMin[d]))*r[idx]-rMin[d]); 
      rInt[idx] = (int)map; 
     } 
     printf("%d %d\n", rInt[DIM*k+0], rInt[DIM*k+1]); 
    } 

    // Convert rInt[x_1,y_1,x_2,y_2,...] to Morton key 
    printf("\n"); 
    unsigned int rMor[n]; 
    for(int k=0; k<n; k++){ 
     int idx = DIM*k; 
     rMor[k] = mortoncode(rInt[idx+0], rInt[idx+1]); 
    } 

    // Sort data 
    sort(rMor, r, n); 

    for(int k=0; k<n; k++){ 
     printf("%lf %lf\n", r[DIM*k+0], r[DIM*k+1]); 
     fprintf(f, "%lf, %lf\n", r[DIM*k+0], r[DIM*k+1]); 

    } 

    return 0; 
} 
+0

'unsigned int rInt [n]'不夠大。在達到'排序前,你可能會遇到錯誤。 –

+0

@cdlane'data.dat'是一個輸出文件,我保存了我的數據。您也可以在終端中看到輸出。參見代碼'printf(「%lf%lf \ n」,r [DIM * k + 0],r [DIM * k + 1]);''和'fprintf(f,「%lf,%lf \ n「,r [DIM * k + 0],r [DIM * k + 1]);'。 – Samuel

+0

@cdlane這不會有太大的幫助。這只是數組'r'的缺陷版本。有'sort'功能的東西一定是錯的。但我沒有發現錯誤。 – Samuel

回答

3

我相信@BarmakShemirani有了答案半打意見前,你聲稱:

RINT就是n * DIM大。

但你寫道:

unsigned int rInt[n]; 

修復,我不使用它,而是通過使rrMor到結構的單一陣列,並呼籲它qsort()測試你的sort()程序。他們基本上產生相同的結果,除了重複的索引,其中一個相對翻轉爲其他放出來:

  qsort       your sort 
index  r0  r1   index  r0  r1 
2456659099 0.400000 0.500000 2456659099 0.400000 1.000000 
2456659099 0.400000 1.000000 2456659099 0.400000 0.500000 

修改後的代碼:

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

#define DIM 2 

typedef struct element { 
    unsigned int m; 
    double r[DIM]; 
} ELEMENT; 

// Sort element structure on member 'm' 

int comparator(const void *p, const void *q) { 

    ELEMENT *a = (ELEMENT *) p; 
    ELEMENT *b = (ELEMENT *) q; 

    return (a->m > b->m) - (a->m < b->m); // compare idiom 
} 

// Create morton key 
unsigned int mortoncode(unsigned int x, unsigned int y) { 
    int answer = 0; 

    for (unsigned int i = 0; i < (sizeof(unsigned int) * 8)/2; i++) { 
     answer |= (((x & (1u << i)) << 2 * i) | ((y & (1u << i)) << (2 * i + 1))); 
    } 

    return answer; 
} 

// Find max/min values 
double maxValue(ELEMENT data[], int n, int d) { 
    double max = data[0].r[d]; 

    for (int k = 0; k < n; k++) { 
     if (max < data[k].r[d]) { 
      max = data[k].r[d]; 
     } 
    } 

    return max; 
} 

double minValue(ELEMENT data[], int n, int d) { 
    double min = data[0].r[d]; 

    for (int k = 0; k < n; k++) { 
     if (min > data[k].r[d]) { 
      min = data[k].r[d]; 
     } 
    } 

    return min; 
} 

int main(int argc, char **argv) { 
    FILE *f = fopen("data.dat", "w"); 
    int n = 100; 
    ELEMENT data[n]; 

    // Initialize data 
    double x1 = 0; 
    double y1 = 0; 

    for (int k = 0; k < n; k++) { 
     data[k].r[0] = x1; 
     data[k].r[1] = y1; 
     x1 += 0.1; 
     if (k % 10 == 0) { 
      y1 += 0.1; 
      x1 = 0; 
     } 
     printf("%lf %lf\n", data[k].r[0], data[k].r[1]); 
    } 
    printf("\n"); 

    // Get max/min values 
    double rMin[DIM]; 
    double rMax[DIM]; 

    for (int d = 0; d < DIM; d++) { 
     rMin[d] = minValue(data, n, d); 
     rMax[d] = maxValue(data, n, d); 
    } 

    // Convert double data to integers 

    unsigned int rInt[DIM * n]; 

    for (int k = 0; k < n; k++) { 
     for (int d = 0; d < DIM; d++) { 
      int idx = DIM * k + d; 
      double map = floor((2097151/(rMax[d] - rMin[d])) * data[k].r[d] - rMin[d]); 
      rInt[idx] = (int) map; 
     } 

     printf("%d %d\n", rInt[DIM * k + 0], rInt[DIM * k + 1]); 
    } 
    printf("\n"); 

    // Convert rInt[x_1, y_1, x_2, y_2, ...] to Morton key 

    for (int k = 0; k < n; k++) { 
     int idx = DIM * k; 
     data[k].m = mortoncode(rInt[idx + 0], rInt[idx + 1]); 
    } 

    // Sort data 
    qsort(data, n, sizeof(ELEMENT), comparator); 

    for (int k = 0; k < n; k++) { 
     printf("%u %lf %lf\n", data[k].m, data[k].r[0], data[k].r[1]); 
     fprintf(f, "%lf, %lf\n", data[k].r[0], data[k].r[1]); 
    } 

    return 0; 
} 

任何時候,你會發現自己創建並行陣列像rrMor,這通常表示您錯過了一個真正的數據結構。

+0

爲了公平地說明OP,他說他還沒有了解C中的結構。這並不能阻止它成爲處理數據的更好方式。在結構中使用'double r [DIM];'而不是'double x;雙y;'我在評論中建議是一種改進;它使'minValue'和'maxValue'函數更簡單。 –

+0

謝謝@JonathanLeffler的評論。我曾經假設'DIM'可能會增加(儘管目前並不是所有代碼都是爲此設置的)。我轉而採用一種結構方法來使用'qsort()'來測試OP自己的'sort()',他將責任歸咎於它。我在兩個索引元素進行比較時發現的差異是討論*穩定*排序概念的錯失機會。 – cdlane

+0

@cdlane感謝您的評論。不幸的是,你的代碼的結果不符合我的期望。排序後產生的'r'元素在繪製線條時不會創建Z曲線。我嘗試了以下九點:對於'r'中的最高座標,我們得到最大的莫頓鍵,反之亦然。當我編譯你的代碼時,最高的莫頓鍵不再與最高座標關聯。你明白這是爲什麼嗎? – Samuel