連結リスト

連続したデータを扱う場合、一般的にはリストや配列を使ってデータを保存・アクセスします。しかし、場合によっては連結リストを使ったほうが高速に処理できることがあります。特に、リストの先頭に要素を何度も追加・削除する必要がある場合は、連結リストのほうが操作が素早く行えます。
連結リストは、最も基本的なデータ構造のひとつです。要素のリストを保持し、新しい要素を追加したり、それらを参照したりします。これは通常の配列やリストと同様の操作が可能です。連結リストを使用する際、それぞれの要素を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
notion image
この実装では、NodeクラスとLinkedListクラスの2つがあります。Nodeクラスにはdataafterという2つの属性があり、dataはノードがもつ値を、afterは次のノードへの参照を表します。LinkedListクラスにはheadという1つの属性があり、リストの最初のノードへの参照を保持します。append()メソッドはリストの末尾に新しいノードを追加し、print()メソッドはリストの要素を出力します。

Doubly Linked List

さらに、双方向連結リストを使うこともできます。双方向連結リストでは、各要素が次の要素と前の要素の両方への参照を持つため、リストを前後どちらの方向にも走査できるようになります。

Linked List Analysis

連結リストを扱ううえで、いくつか重要なポイントがあります:
  • 連結リストの要素にアクセスするときは、先頭(ヘッド)から辿る必要があるため、要素のアクセスにかかる時間は です。
  • どのノードの後ろに新しい要素を挿入するか分かっている場合、その挿入操作は参照の更新だけで済むため で行えます。
  • どのノードを削除すべきか分かっている場合も、同様に参照の更新だけで済むため削除は となります。
  • 各要素が追加の参照を持つため、連結リストは配列よりも多くのメモリを消費します。

Challenge

与えられた n 個のクエリを実行するプログラムを作成してください。クエリには2種類があります:
  1. リストの先頭に数値を挿入する
  1. リスト全体を出力する

入力

最初の行にはクエリの数 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

To check your solution you need to sign in
Sign in to continue