2013-12-10 4 views
1

Вопрос, который я задал в терминах модели иссечения, состоит в том, чтобы прокручивать 2D-массив с помощью указателей и идентифицировать 4 ближайших соседа с периодическими граничными условиями.Пролистание 2-мерных массивов с использованием указателей с граничными условиями

Это мой код;

#include <stdio.h> 
#include <stdlib.h> 
int Lattice_Size=100; 


main() 
{ 
int *ptr, *mat; 
int i, j ; 
int spin_up = 1; 
int spin_down = -1; 

mat = (int *)malloc(sizeof(int)*Lattice_Size*Lattice_Size);    // dynamic memory for Lattice 
ptr = mat; 

for (i=0; i<Lattice_Size; i++) 
{ 
     for (j=0; j<Lattice_Size; j++) 
    { 
     *ptr++=spin_up;        // initilizing to parallel spins 
     } 
    } 
free(mat); 
mat=NULL; 

}

Я озадачен Теперь о том, как несутся через решетку и найти ближайших соседей. Я математически знаю, как описывать граничные условия, но я не знаю, как его кодировать.

ответ

3

При сохранении 2D данных в линейном (по существу) массив N * N, вы можете найти элемент (I, J) с

element(i,j) = array[j + N * i]; 

"периодические граничные условия" (имеется в виду - если вы падаете от нижней части вы идете к вершине, и если вы упадете слева вы повторно ввести справа) может быть описана следующим образом:

element(i - 1, j) = (i == 0)  ? array[ j + N * (N - 1) ] : array[ j + N * i ]; 
element(i + 1, j) = (i == N - 1) ? array[ j ]    : array[ j + N * i ]; 
element(i, j - 1) = (j == 0)  ? array[ N - 1 + N * i] : array[ j + N * i ]; 
element(i, j + 1) = (j == N - 1) ? array[ N * i ]   : array[ j + N * i ]; 

Проверьте свою математику, но я уверен, что это правильно.

PS на личном Примечание: очень первая программа, которую я когда-либо писал (в 1975 году, используя ALGOL 68) необходимо, чтобы я использовал обнаружить) именно этот трюк (падение с края и вновь появиться на другой стороне) чтобы сделать волшебный квадрат. Спасибо за эту поездку вниз по полосе памяти.

EDIT Я решил написать еще несколько функций - вы увидите, как это сделает ваш основной код более читаемым. Я добавил комментарии, чтобы помочь в вашем понимании.

include <stdio.h> 
#include <stdlib.h> 
int Lattice_Size=10; 

// some code to handle a matrix with wrapping at the edges 
// as might be useful in lattice spin analysis 
// note - assumption is that grid is same size in i and j direction 
// code needs minor modifcation if grid is non-square 

int getElement(int *p, int i, int j, int n) { 
// find element with wrapping 
i = (i + n) % n; 
j = (j + n) % n; 
return p[ i * n + j ]; 
} 

int setElement(int *p, int i, int j, int n, int val) { 
// set the i, j element to value val 
// if the element points "off the edge" 
// this code puts it back in the range [0, n-1] 
// for both i and j 
// assuming i, j are not "very negative" (i.e. i+n is always > 0) 
// this will be the case when "off the edge" is by a single step 
// could write i = (i < 0) ? (i % n) + n : i % n; 
// if this has to work for any values of i (ditto j) 
// but that is slower 
    i = (i + n) % n; // coerce in range: takes care of wrapping 
    j = (j + n) % n; 
    p[ i * n + j ] = val; 
    return val; // could make this void function and not return anything 
} 

void setNeighbors(int *p, int i, int j, int n, int val) { 
// set 4 nearest neighbors to value val 
// with wrapping (if you fall off the left edge 
// you re-appear on the right) 
    setElement(p, i + 1, j , n, val); 
    setElement(p, i - 1, j , n, val); 
    setElement(p, i , j + 1, n, val); 
    setElement(p, i , j - 1, n, val); 
    return; // return nothing: void function 
} 

int* getNeighbors(int *p, int i, int j, int n, int dest[4]) { 
// return the 4 neighbors (with wrapping) 
// in space allocated in dest[4] 
// order: N, E, S, W 
    dest[0] = getElement(p, i - 1, j , n); 
    dest[1] = getElement(p, i , j + 1, n); 
    dest[2] = getElement(p, i + 1, j , n); 
    dest[3] = getElement(p, i , j - 1, n); 
    return dest; // return pointer to neighbor elements (same as input pointer) 
} 

void printMatrix(int* mat, int n) { 
// print a simple square matrix 
// with fixed width formatting 
// and sign appended 
    int i, j; 
    for(i = 0; i < n; i++) { 
    for(j = 0; j < n; j++) { 
     printf("%+2d ", getElement(mat, i, j, n)); 
    } 
    printf("\n"); 
    } 
} 

main() 
{ 
int *ptr, *mat; 
int i, j ; 
int spin_up = 1; 
int spin_down = -1; 
int neighbors[4]; 

// allocate memory for the spin matrix: 
mat = (int *)malloc(sizeof(int)*Lattice_Size*Lattice_Size); 
ptr = mat; // copy pointer 

for (i=0; i<Lattice_Size; i++) 
{ 
    for (j=0; j<Lattice_Size; j++) 
    { 
     *ptr++=spin_up; // initializing to parallel spins 
          // this could be done with setElement(mat, i, j, Lattice_Size); 
          // for greater readability 
    } 
} 
// change a few elements to different values: 
setElement(mat, 2, 3, Lattice_Size, 2); 
setElement(mat, 5, 0, Lattice_Size, 3); 
// set the neighbors of an element on the edge: 
setNeighbors(mat, 5, 0, Lattice_Size, -1); 
// print the result 
printMatrix(mat, Lattice_Size); 
// read back the 4 neighbors of an element on the edge: 
getNeighbors(mat, 4, 0, Lattice_Size, neighbors); 
// print the result: 
printf("neighbors of (4,0):\n"); 
for (i = 0; i < 4; i++) printf("%+2d ", neighbors[i]); 
printf("\n"); 

// clean up: 
free(mat); 
mat=NULL; 
} 

Пример вывода из вышеперечисленных:

+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
+1 +1 +1 +2 +1 +1 +1 +1 +1 +1 
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
-1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
+3 -1 +1 +1 +1 +1 +1 +1 +1 -1 
-1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 
neighbors of (4,0): 
+1 +1 +3 +1 

Как можно видеть, элемент (2,3) (два вниз, три поперек) действительно установлено до +2; элемент (5, 0) установлен в значение +3; и соседние элементы (4,0) являются (по часовой стрелке сверху) 1, 1, 3, 1 (это значение от правого края ...)

Играйте с ним и дайте мне знать, если что-нибудь еще не ясно.

+0

Рассматривая мой код снова этим утром, я попытался установить printf («% d \ n», * mat); команда, чтобы увидеть, была ли моя матрица похожей на массив из 1, но все, что я получил, было одиночным 0, это правильно? – user3086838

+0

Ваша команда будет печатать только значение 'mat [0]' (это то, что означает '* mat' - содержимое места, на которое указывает' mat'). Вы хотите, чтобы это было равным нулю? Надеюсь, вы сделали это до операции «бесплатно». – Floris

+0

Я сделал, я просто очень смущен, как все это работает, мне нужно задавать вопросы, но я не знаю, на какой вопрос спросить. Хорошо, я скомпилировал ваш код, спасибо вам большое. Мне нужно кое-что уточнить, я не понимаю, как функции получают элемент и задают элемент. Кроме того, что вы подразумеваете под dest [4], и почему у вас есть% 4d в матрице печати, как указано в% d? – user3086838

Смежные вопросы