2015年6月29日 星期一

改善記憶體管理效能




上篇的動態配置記憶空間做法,每加入一筆資料就要重新產生新的空間,還要把舊資料 copy 過去,效率非常差。若是一開始就先配置一段大小適中的記憶空間,可以直接儲存每次輸入的資料,而在空間用完的時候才去配置新的空間,這樣就可以在執行效能和記憶體需求之間取得平衡。而每次配置的空間應該多大,需評估輸入資料產生的速度,資料輸入越快越多,就應配置更大的空間。

#include <iostream>

class myData
{
//私有區段,只有class內部程式可存取
private:
   //Data member
   int _boundary; //陣列空間上限 

//公用區段,class內外部程式均可存取
public:
   //Data member
   int len;
   int *data; //用來存放所有輸入資料的記憶空間指標
     
   //Member function
   myData() //建構函式,當物件產生時會自動執行
   {
     len=0; //資料長度歸0
     _boundary=10; //邊界設為10 
     data=new int[_boundary]; //配置10個int記憶空間 
   }

   ~myData() //解構函式,當物件消滅時會自動執行
   {
     delete [] data; //釋放data記憶空間
   }

   void add(int d)
   {
     if (len>=_boundary-1) //資料滿了,增加記憶空間
     {
       int *newptr=new int[_boundary+10]; //動態配置比原來多10個int記憶空間
       for(int i=0; i<len; i++)
         newptr[i]=data[i]; //把舊資料複製到新的位置
       delete [] data; //釋放舊的記憶空間
       data=newptr; //資料指標指向新的位置
       _boundary+=10;
     }
     data[len++]=d; //把參數d放在最後的位置後再把資料長度+1
   }
};

int common_divisor(int a, int b) //遞迴函式1
{
    return (a%b==0) ? b : common_divisor(b,a%b); //交換位置輾轉相除
}

int common_divisor(int d[], int n) //遞迴函式2
{
   if(n==1)
     return d[0];
   if(n==2)
     return common_divisor(d[0],d[1]); //呼叫遞迴函式1
   if(n>2)
     return common_divisor(common_divisor(d,n/2),
                           common_divisor(&d[n/2],n-n/2) ); //呼叫遞迴函式2 

   return 0; //n小於1才會發生
}

int main()
{
   int d;
   class myData object1;

   std::cout << "請輸入n個正整數,輸入完成請按 Ctrl-Z" << std::endl;
   while ( std::cin >> d )
      object1.add(d);
   
   std::cout << "最大公因數=" << common_divisor(object1.data,object1.len);
   return 0;

}

沒有留言:

張貼留言