リンクリストには、単方向リンクリスト、双方向リンクリストなどがあります。ここでは、単方向リンクリストについてやってみます。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
btnAdd: TButton;
btnShow: TButton;
ListBox1: TListBox;
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
procedure FormCreate(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure btnShowClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
pMyRecord = ^TMyRecord;
TMyRecord = record
Name: string;
Age: Integer;
Next: pMyRecord;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
Start: pMyRecord;
CurrentPosition: pMyRecord;
procedure TForm1.FormCreate(Sender: TObject);
begin
// 基点を生成。
New(Start);
Start^.Name := '基点です。';
Start^.Age := 0;
Start^.Next := nil;
CurrentPosition := Start;
end;
procedure TForm1.btnAddClick(Sender: TObject);
var
Current: pMyRecord;
begin
New(Current);
Current^.Name := Edit1.Text;
if not TryStrToInt(Edit2.Text, Current^.Age) then
begin
ShowMessage('変換できません。');
Dispose(Current);
exit;
end;
Current^.Next := CurrentPosition;
CurrentPosition := Current;
ShowMessage('追加しました。');
end;
procedure TForm1.btnShowClick(Sender: TObject);
var
temp: pMyRecord;
begin
ListBox1.Clear;
temp := CurrentPosition;
while temp^.Next <> nil do
begin
ListBox1.Items.Add(temp^.Name + ' ' +
IntToStr(temp^.Age));
temp := temp^.Next;
end;
ListBox1.Items.Add(temp^.Name + ' ' +
IntToStr(temp^.Age));
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
temp: pMyRecord;
begin
while CurrentPosition^.Next <> nil do
begin
temp := CurrentPosition^.Next;
Dispose(CurrentPosition);
CurrentPosition := temp;
end;
Dispose(CurrentPosition);
end;
end.
TMyRecord の中にそれ自身を指すポインタを持つ事で、レコードを次々に結び付けていっています。図にしますと以下のようになります。
基点となるレコードの Next には nil を指すようにしておくことがポイントです。
実行すると上記のようになります。
つながっているリストの任意の間に、新たなリストを挿入してみましょう。サンプルは、以下のようになります。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btnInsert: TButton;
btnShow: TButton;
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure btnShowClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnInsertClick(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
pMyRecord = ^TMyRecord;
TMyRecord = record
Name: string;
Age: Integer;
Next: pMyRecord;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
Start,
CurrentPosition: pMyRecord;
procedure Init;
begin
New(Start);
Start^.Name := 'Hello0';
Start^.Age := 0;
Start^.Next := nil;
CurrentPosition := Start;
end;
procedure SetUp;
var
Current: pMyRecord;
i: Integer;
begin
for i := 0 to 3 do
begin
New(Current);
Current^.Name := 'Hello' + IntToStr(i+1);
Current^.Age := 2 * (i);
Current^.Next := CurrentPosition;
CurrentPosition := Current;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Init;
SetUp;
end;
procedure TForm1.btnShowClick(Sender: TObject);
var
temp: pMyRecord;
begin
ListBox1.Clear;
temp := CurrentPosition;
while temp^.Next <> do
begin
ListBox1.Items.Add(temp^.Name + ' ' +
IntToStr(temp^.Age));
temp := temp^.Next;
end;
ListBox1.Items.Add(temp^.Name + ' ' +
IntToStr(temp^.Age));
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
temp: pMyRecord;
begin
while CurrentPosition^.Next <> nil do
begin
temp := CurrentPosition^.Next;
Dispose(CurrentPosition);
CurrentPosition := temp;
end;
Dispose(CurrentPosition);
end;
procedure TForm1.btnInsertClick(Sender: TObject);
var
insert: pMyRecord;
temp: pMyRecord;
begin
New(insert);
insert^.Name := 'world';
insert^.Age := 11;
temp := CurrentPosition;
insert^.Next := temp^.Next.Next;
temp^.Next.Next := insert;
end;
end.
図で表しますと、以下のようになります。
リストの間に挟みこむような感じになっています。
ちゃんと挿入されているようです。
リストの削除のサンプルです。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btnDelete: TButton;
btnShow: TButton;
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure btnShowClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
pMyRecord = ^TMyRecord;
TMyRecord = record
Name: string;
Age: Integer;
Next: pMyRecord;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
Start,
CurrentPosition: pMyRecord;
procedure Init;
begin
New(Start);
Start^.Name := 'Hello0';
Start^.Age := 0;
Start^.Next := nil;
CurrentPosition := Start;
end;
procedure SetUp;
var
Current: pMyRecord;
i: Integer;
begin
for i := 0 to 3 do
begin
New(Current);
Current^.Name := 'Hello'+IntToStr(i+1);
Current^.Age := 2*i;
Current^.Next := CurrentPosition;
CurrentPosition := Current;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
init;
SetUp;
end;
procedure TForm1.btnShowClick(Sender: TObject);
var
temp: pMyRecord;
begin
ListBox1.Clear;
temp := CurrentPosition;
while temp^.Next <> do
begin
ListBox1.Items.Add(temp^.Name + ' ' +
IntToStr(temp^.Age));
temp := temp^.Next;
end;
ListBox1.Items.Add(temp^.Name + ' ' +
IntToStr(temp^.Age));
end;
procedure TForm1.btnDeleteClick(Sender: TObject);
var
delete: pMyRecord;
begin
delete := CurrentPosition^.Next;
CurrentPosition^.Next := CurrentPosition^.Next.Next;
Dispose(delete);
btnDelete.Enabled := false; // 複数回押されるのを防ぐ
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
temp: pMyRecord;
begin
while CurrentPosition^.Next <> nil do
begin
temp := CurrentPosition^.Next;
Dispose(CurrentPosition);
CurrentPosition := temp;
end;
Dispose(CurrentPosition);
end;
end.
リストの挿入の場合と同様な考え方で、削除を行います。
btnDelete ボタンを押してから、btnShow ボタンを押すと上記のようになります。