PDA

View Full Version : بهترین روش تخصیص حافظه ماتریس در c++



lalecarbon
دوشنبه 15 مهر 1392, 21:51 عصر
سلام به همه ی دوستان
روشی که برای اختصاص حافظه به ماتریس استفاده می شود، معمولا به شکل زیر است:


int **Array;
for(int i=0;i<rows;i++)
Array[i]=new int [cols];


این روش حافظه را به صورت پراکنده به ماتریس تخصیص می دهد.
هدف من، قرار گرفتن خانه های ماتریس به صورت پشت سر هم در حافظه است. به عنوان مثال، یک ماتریس 4*4 در حافظه به صورت 16 خانه پشت سر هم قرار گیرد.
اکنون اگر بخواهیم اختصاص حافظه به خانه های ماتریس را به صورت پشت سر هم قرار دهیم، پیشنهاد شما چیشت؟

rahnema1
دوشنبه 15 مهر 1392, 23:15 عصر
سلام به همه ی دوستان
روشی که برای اختصاص حافظه به ماتریس استفاده می شود، معمولا به شکل زیر است:


int **Array;
for(int i=0;i<rows;i++)
Array[i]=new int [cols];


این روش حافظه را به صورت پراکنده به ماتریس تخصیص می دهد.
هدف من، قرار گرفتن خانه های ماتریس به صورت پشت سر هم در حافظه است. به عنوان مثال، یک ماتریس 4*4 در حافظه به صورت 16 خانه پشت سر هم قرار گیرد.
اکنون اگر بخواهیم اختصاص حافظه به خانه های ماتریس را به صورت پشت سر هم قرار دهیم، پیشنهاد شما چیشت؟

شما می تونید حافظه رو به صورت پیوسته allocate کنید یعنی اون رو به شکل لیت ببینید یعنی 16 تاو بعد هنگام پیمایش و مقدار دهی به اون به شکل یک ماتریس نگاه کنید مثلا



long int x,y;
int *arr,xsize,ysize;
arr=(int *) malloc (ysize*xsize);
for (y=0;y<ysize;y++)
for(x=0;x<xsize;x++)
arr[(y*xsize)+x]=x*x+y*y;

Ananas
سه شنبه 16 مهر 1392, 16:12 عصر
سلام.
اگر سایز ماتریستون مشخصه پیشنهاد من استفاده از struct هست. دقیقا مثال 4 در 4 شما رو directx به شکل struct تعریف کرده:

typedef struct _D3DMATRIX {
union {
struct {
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;

};
float m[4][4];
};
} D3DMATRIX;

این کد در فایل d3d9types.h هست و استفاده از union کمک میکنه تا شما هم از طریق نام عناصر و هم از طریق اندیس آرایه، بهشون دسترسی داشته باشین.

omidshaman
سه شنبه 16 مهر 1392, 23:02 عصر
یک نمونه ساده برات نوشتم با استفاده از template ها میتونی تعمیمش هم بدی .
سریع تر بودنشو نمیدونم ولی استفاده ازش از اون روش خودت ساده تره( MyArray test(4,6)l )


#include <iostream>
using namespace std;

class MyArray{
public:
MyArray(int i,int j)
{
container=new int[i*j];
}

~MyArray()
{
delete[] container;
}
class Proxy//baraye estefade az operator [][]
{
public :
Proxy(int *arr,int iIndex)
:arr(arr),
iIndex(iIndex){}
int& operator [](int index)
{
jIndex=index;
return arr[iIndex*4+index-1];
}
void operator =(int number)
{
arr[iIndex*4+jIndex-1]=number;
}
//operator += -= *= ,....
private:
int *arr;
int iIndex;
int jIndex;

};

Proxy operator [](int index)
{
return Proxy(container,index);
}

private:
int *container;

};
int main()
{
MyArray test(4,6);

int z=0;
for(int i=0;i<4;i++)
for(int j=0;j<6;j++)
test[i][j]=z++;
for(int i=0;i<4;i++)
{
for(int j=0;j<6;j++)
cout<<test[i][j]<<" ";
cout<<"\n";
}
return 0;
}

lalecarbon
سه شنبه 16 مهر 1392, 23:13 عصر
ممنون از جواباتون.
تعداد درایه ها ثابت نیست و طول ماتریس تغییر می کند.

rahnema1
چهارشنبه 17 مهر 1392, 06:22 صبح
ممنون از جواباتون.
تعداد درایه ها ثابت نیست و طول ماتریس تغییر می کند.

اگه حافظه به مقدار کافی داشته باشید به اندازه چهار برابر فضای اشغال شده بزرگترین ماتریسی که در حین
برنامه ایجاد خواهد شد فضا allocate کنید البته چهار برابر وحی منزل نیست می تونه کمتر یا بیشتر باشه اما
نباید از فضای بزرگترین ماتریس کمتر باشه و هر چه هم بیشتر باشه دردسرش کمتره
ماتریس مورد نظر را داخل آن فضا قرار دهید و همان طور که در پست قبلی اشاره کردم از طریق اندیس دهی با
فضای یک بعدی بصورت ماتریس دو بعدی کار کنید
مثلا فرض کنید ماتریس اولیه 100*100 باشد ما به اندازه 40000=4*100*100 فضا allocate می کنیم که می تونیم
اون رو بعنوان یک ماتریس 200*200 در نظر بگیریم. بعدش هم مربع 100*100 را دقیقا در وسط مربع 200*200 قرار
می دهیم. به اندیس شروع و پیمایش ماتریس وسطی توجه کنید
توی برنامه زیر قراره مقدار ماتریس وسطی رو به 1 تغییر بدیم



int *buffer,row,col,rows,cols,startrow,startcol,endrow ,endcol;
rows=200;
cols=200;
startrow=49;
startcol=49;
endrow=149;
endcol=149;
buffer=(int *) calloc (rows*cols,sizeof(int));
for (row=startrow;row<=endrow;row++)
for(col=startcol;col<=endcol;col++)
buffer[(row*cols)+col]=1;


کاهش یا افزایش اندازه ماتریس

اگه توسعه یا کاهش اندازه ماتریس از طرف حاشیه های آن انجام بشه که کار خیلی راحت می شه توی این حالت فقط کافیه اندیس شروع یا پایان پیمایش با ماتریس وسطی رو تغییر بدیم
توی برنامه زیر دو تا ستون از سمت چپ به ماتریس وسطی اضافه می شه



for(col=startcol-2;col<=startcol;col++)
for (row=startrow;row<=endrow;row++)
buffer[(row*cols)+col]=1;
startcol=startcol-2;



اگه قراره یک یا چند سطر و یا ستون از وسط ماتریس حذف یا اضافه بشه علاوه بر تغییر اندیس شروع یا پایان،
باید مقادیر حافظه هم جابجا بشن که این کار نسبت به حالت قبل برای سیستم یک بار اضافی ایجاد می کنه
توی برنامه زیر سطر هشتادم از ماتریس وسطی حذف میشه



for (row=startrow+81;row<=endrow;row++)
for(col=startcol;col<=endcol;col++)
buffer[((row-1)*cols)+col]=buffer[(row*cols)+col];
endrow=endrow-1;

Ananas
چهارشنبه 17 مهر 1392, 06:44 صبح
typedef class TMatrixWxH
{
private:
int __W;
int __H;
int * __pData;
public:
TMatrixWxH(int W, int H)
{
__W = W;
__H = H;
__pData = NULL;
SetNewSize(W, H);
};
~TMatrixWxH()
{
free(__pData);
};
int GetWidth() { return __W; };
int GetHeight() { return __H; };
void SetNewSize(int W, int H)
{
size_t NewSize = sizeof(int) * W * H;
if (__pData == NULL)
{
__pData = (int *)malloc(NewSize);
}
else
{
realloc(__pData, NewSize);
};
__W = W;
__H = H;
};
int & JI(int J, int I)
{
return __pData[J * __H + I];
};
int * operator [](int J)
{
return &__pData[J * __H];
};
} *PMatrixWxH;