連結リスト
連続したデータを扱う場合、一般的にはリストや配列を使ってデータを保存・アクセスします。しかし、場合によっては連結リストを使ったほうが高速に処理できることがあります。特に、リストの先頭に要素を何度も追加・削除する必要がある場合は、連結リストのほうが操作が素早く行えます。
連結リストは、最も基本的なデータ構造のひとつです。要素のリストを保持し、新しい要素を追加したり、それらを参照したりします。これは通常の配列やリストと同様の操作が可能です。連結リストを使用する際、それぞれの要素を
Node
と呼び、このNode
にはデータと次のNode
へのリンクが含まれています。単方向の連結リストでは、各Node
が次のノードへの参照を持ち、最後のノードは何も参照せず(null
)終わります。一般的な文献では、先頭の要素を「ヘッド(head)」、末尾の要素を「テイル(tail)」と呼びます。連結リストの実装例として、以下のような形が考えられます。class Node:
def __init__(self, data):
self.data = data # データを保持する
self.after = None # 次の要素へのリンクを保持する
class LinkedList:
def __init__(self):
self.head = None # 初期状態では要素が存在しない
def append(self, data): # 新しい要素をリストに追加する
new_node = Node(data) # dataを保持するノードを作成する
if self.head is None: # リストに要素がない場合
self.head = new_node # ヘッドを新しいノードに設定する
return
current = self.head # ヘッドからリストをたどり始める
while current.after: # テイルに到達していない限り
current = current.after # 次のノードに移る
current.after = new_node # テイルを更新し、新しいノードを設定する
def print(self): # リスト内のすべての要素を出力する
current = self.head # ヘッドから開始する
while current: # リストの末端に到達していない限り
print(current.data, end='\n' if current.after is None else ' --> ')
current = current.after # 次のノードに移る
names = LinkedList() # 空の連結リストを作成する
names.append('Anna') # リストにAnnaを追加する
names.append('Bob') # リストにBobを追加する
names.append('Sona') # リストにSonaを追加する
names.print() # Anna --> Bob --> Sona

この実装では、
Node
クラスとLinkedList
クラスの2つがあります。Node
クラスにはdata
とafter
という2つの属性があり、data
はノードがもつ値を、after
は次のノードへの参照を表します。LinkedList
クラスにはhead
という1つの属性があり、リストの最初のノードへの参照を保持します。append()
メソッドはリストの末尾に新しいノードを追加し、print()
メソッドはリストの要素を出力します。 Doubly Linked List
さらに、双方向連結リストを使うこともできます。双方向連結リストでは、各要素が次の要素と前の要素の両方への参照を持つため、リストを前後どちらの方向にも走査できるようになります。
Linked List Analysis
連結リストを扱ううえで、いくつか重要なポイントがあります:
- 連結リストの要素にアクセスするときは、先頭(ヘッド)から辿る必要があるため、要素のアクセスにかかる時間は です。
- どのノードの後ろに新しい要素を挿入するか分かっている場合、その挿入操作は参照の更新だけで済むため で行えます。
- どのノードを削除すべきか分かっている場合も、同様に参照の更新だけで済むため削除は となります。
- 各要素が追加の参照を持つため、連結リストは配列よりも多くのメモリを消費します。
Challenge
与えられた
n
個のクエリを実行するプログラムを作成してください。クエリには2種類があります:- リストの先頭に数値を挿入する
- リスト全体を出力する
入力
最初の行にはクエリの数
n
(1 ≤ n ≤ 1000) が与えられます。続く
n
行にはクエリが与えられます。print
と書かれている場合はリスト全体を出力し、insert x
と書かれている場合は数値 x
をリストの先頭に挿入する必要があります ( ≤ x ≤ )。 出力
プログラムはすべてのクエリを正しく処理し、リストの要素をスペース区切りで出力してください。
例
Input | Output |
6
insert 8
print
insert 10
insert -2
insert -6
print | 8
-6 -2 10 8 |
Constraints
Time limit: 2 seconds
Memory limit: 512 MB
Output limit: 1 MB