 

(1)考え方
CやC++では,calloc関数,free関数を使って,
領域の確保・開放を行い,
ポインタでデータを参照することがよく行われますが,
C#では,安全なプログラミングの観点から
ポインタの使用は推奨されていません。
したがって,次のように
あえてUnsafeを指定することになっています。
unsafe
{
char* p=stackalloc char[256];
for (int i=0; i<256;i++) *(p+i)=(char)i;
int* values = stackalloc int[20];
int* a= & values[1];
int* b= & values[15];
MessageBox.Show
(string.Format(" a
- b =
{0} \n b - a = {1}",a-b,b-a));
}
しかし,リスト構造等を扱うとき,頻繁にデータ確保,開放
を行う必要があります。
一方,バグが潜む多くは,領域確保・開放の部分です。
ですから,領域確保・開放をシステム任せにしないで,
自分が制御できる範囲内で領域確保・開放を行いたいものです。
このようなとき,配列領域を分割して,動的に管理します。
  
(2)初期化
最初,次のように各要素のリストを作っておきます。

[プログラム処理](空ポインタを-1とする)
public struct ElementData
{
public long 番号;
public string 氏名;
public int 点数;
}
public struct ElementSet
{
public ElementData Element;
public long Next;
}
public ElementSet[] DataArea = new ElementSet[500];
public long ErasedP; // 未使用領域の先頭領域
private void 初期化( )
{
for(int i=0;i<DataArea.Length-1;i++)
DataArea[i].Next=i+1;
DataArea[DataArea.Length-1].Next=-1;
ErasedP=0;
}
  
(3)領域の確保
最初,次のように各要素のリストを作っておきます。
未使用ポインタが指している要素を使うものとします。
すなわち,以下の手順で処理します。
@)未使用ポインタを関数値とする
A)未使用ポインタが指しているポインタを未使用ポインタとする。
[プログラム例]
private long GetArea( )
{
long R = ErasedP;
ErasedP = DataArea[ErasedP].Next;
return R;
}
  
(4)領域の返却
領域の返却とは,指定された要素を未使用領域の管理下に
戻すことです。すなわち,
@)未使用ポインタの内容を返却領域のポインタとする。
A)未使用ポインタを返却領域へのポインタとする。
の手順で行います。
[プログラム例]
private void FreeArea(long P)
{
if(P<0) return;
DataArea[P].Next=ErasedP;
ErasedP = P;
}
すでに,未使用要素であるような領域を返却すると,
未使用のリストが網状になってしまい,
未使用・使用の関係がメチャメチャになり
悲惨なことになることが多くあります。
したがってデバッグ時には,
以下のように返却されようとする要素が,
未使用領域でないかどうかを判定する処理を追加して
テストを行うことが多いようです。
[デバッグ時のプログラム例]
private void FreeArea(long P)
{
if(P<0) return;
// ***以下,チェック用***
long PP = ErasedP;
while(PP>=0)
{
if(PP==P)
{
MessageBox.Show("領域"+P.ToString()
+"はフリーエリアです");
return;
}
PP=next(PP);
}
// ****チェックここまで***
DataArea[P].Next=ErasedP;
ErasedP = P;
}
  
1. 基本的なアルゴリズム
2. 基本的なデータ構造
3. 操作を伴うデータ構造
4. 探索
5. 再帰的アルゴリズム
6. ソート
7. 集合
8. 文字列処理
9. 色々なアルゴリズム

上のタイトルをクリックします
|