行き交う列車の多い鉄道網のために、列車のスケジュール管理システムを開発するプロジェクトに取り組んでいます。
そのスケジュール管理システムで使う列車の路線のプロトタイプを作るように頼まれました。それぞれの路線は、ある列車が停車する駅を順番に並べたものです。
チームは、スケジュールにある各列車の路線を双方向連結リストで表すことに決めました。 列車の路線上にある各駅は、連結リストのノードで表します。
駅の到着時刻や出発時刻を気にする必要はありません。 各駅は、単に数値で表します。
路線は延長できます。路線の先頭または末尾に駅を追加します。 また、路線の先頭または末尾から駅を削除して短くすることもできます。
駅が廃止されることがあり、その場合は路線の先頭や末尾でなくても、その駅を路線から削除する必要があります。
路線の大きさは、列車が走る距離ではなく、停車する駅の数で測ります。
連結リストは、コンピューターサイエンスにおける基本的なデータ構造で、ほかのデータ構造の実装によく使われます。 名前のとおり、つながり合ったノードのリストです。 「ノード」のリストで、それぞれのノードが隣のノード(複数の場合もあります)とつながっています。 単方向連結リストでは、各ノードは後ろのノードだけとつながります。 双方向連結リストでは、各ノードは前のノードと後ろのノードの両方とつながります。
連結リストについてもっと深く知りたい場合は、わかりやすい図で解説しているこちらの記事を見てみましょう。
双方向連結リストを実装します。
値と、次のノードおよび前のノードへのポインターを保持するNodeを実装してください。
次に、先頭と末尾のノードへの参照を保持し、要素の追加と削除のための関数を提供するListを実装します。
Nodeには、次のフィールドとメソッドが必要です。
Value:ノードの値(ここではanyを使います)。Next() *Node:次のノードへのポインター。Prev() *Node:前のノードへのポインター。Listを作成して返すNewList()という関数も必要です。
NewList(args ...any) *List:値の順序を保った新しい連結リストを作成します。Listには、次のメソッドが必要です。
First() *Node:先頭のノード(head)へのポインターを返します。Last() *Node:末尾のノード(tail)へのポインターを返します。Push(v any):リストの末尾に値を挿入します。Pop() (any, error):リストの末尾から値を取り除きます。Unshift(v any):リストの先頭に値を挿入します。Shift() (any, error):リストの先頭から値を取り除きます。Reverse():連結リストを逆順にします。