リンクリストには、単方向リンクリスト、双方向リンクリストなどがあります。ここでは、単方向リンクリストについてやってみます。
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 ボタンを押すと上記のようになります。