google-site-verification=KwoyNUeKe7VDQiI7kfq9Jyto1RpwO7D9Qcqdh6qhaWc

【Python】線形リスト(連結リスト)【アルゴリズム】

Pythonでアルゴリズムの線形リスト(連結リスト)の解説をします。



リスト

データが順序付けられて並んでいるデータ構造をリストといいます。

Pythonの組込み型のリスト型(list型)とは違います。

リストの中でも最も単純な構造なのが今回の線形リストです。

まず考えるのが配列xには1、2、3、4、5という5個の要素と空の要素2個の合計7個の要素が格納されているとします。

この配列xにおいて1と2の間の要素に9を追加することを考えます。

挿入前 0 1 2 3 4 5 6
1 2 3 4 5
挿入後 0 1 2 3 4 5 6
1 9 2 3 4 5

挿入後ではx[1]に9を入れるためにx[2]以降のすべての要素をひとつ後ろの要素に移動しています。

今回は移動させる要素数がそこまで多くないですが、これが何千や何万ともなるとかなりのコストになります。

削除する際も同様な処理が必要で効率はよくないです。

線形リスト(連結リスト)

線形リスト(linear list)はデータを鎖状につなぐデータ構造です。

連結リスト(linked list)とも呼ばれています。

下の表は線形リストを図式化したものです。

なおこの線形リストではAからEまでのデータが先頭から順に並んでいるものとします。

位置 先頭
ノード
参照先   参照先   参照先   参照先 末尾
ノード
ノード データ A B C D E
ポインタ          

リスト中の個々の要素をノードといい、ノードはデータとひとつ後ろのノードを参照するポインタで構成されています。

先頭にあるノードを先頭ノードといい、末尾にあるノードを末尾ノードといいます。

ひとつ先頭側にあるノードを先行ノード、ひとつ末尾側にあるノードを後続ノードといいます。

なおこのサイトではポインタに参照ノードがある場合は水色、ない場合は灰色で表しています。

ノードについて図示したものが以下の通りです。

Node 参照先 Node
data    
next    

ノードをNode、データをdataとします。

各ノード内で後続ノードを指すポインタを後続ポインタnextとします。

ただし末尾ノードは後続ノードが存在しないのでnextの値はNoneとします。

これらをプログラムで表すことを考えます。



ノードクラスNode

# 線形リスト

from __future__ import annotations
from typing import Any, Type

class Node:
    """線形リスト用ノードクラス"""

    def __init__(self, data: Any = None, next: Node = None):
        """初期化"""
        self.data = data  # データ
        self.next = next  # 後続ポインタ

フィールド

ノードクラスNodeには2つのフィールドがあります。

フィー
ルド名
内容


data データ


任意

next 後続ポインタ


Node型

__init__メソッド

__init__メソッドでは引数のdataとnextを対応するフィールドに代入して初期化します。

引数が省略された場合はNoneが代入されるようになっています。

線形リストクラスLinkedList

class LinkedList:
    """線形リストクラス"""

    def __init__(self) -> None:
        """初期化"""
        self.no = 0          # ノードの個数
        self.head = None     # 先頭ノードへの参照
        self.current = None  # 着目ノードへの参照

    def __len__(self) -> int:
        """線形リスト上のノード数を返却"""
        return self.no

フィールド

線形リストクラスLinkedListには3つのフィールドがあります。

フィー
ルド名
内容
no リスト上のノードの個数
head 先頭ノードへの参照
current 現在着目しているノードへの参照

__init__メソッド

__init__メソッドではノードが0個の空の線形リストを生成します。

headは先頭ノードへの参照であって、先頭ノードそのものではありません。

ノードがないということはheadが参照するノードが存在しないため値はNoneになります。

もちろんノードがないということは着目するノードも存在しないのでcurrentも値はNoneです。

ノードの個数によってnextがどうなるか見ていきます。

ノードが0個の線形リスト

head  

線形リストにノードがないのでheadが参照するノードが存在しません。

そのためheadの値はNoneとなるため、以下の式が成立すれば空の線形リストだと判断できます。

head is None

ノードが1個の線形リスト

head  
参照先
ノードA head
.data
A
head
.next
 

headの参照先は先頭ノードAです。

線形リストのノードは1個なので先頭ノードAは末尾ノードでもあります。

末尾ノードであるということは後続ノードはありません。

後続ポインタはnextなのでノードAの後続ポインタhead.nextの値はNoneということになります。

そのため以下の式が成立すればノードが1個の線形リストだと判断できます。

head.next is None

ノードが2個の線形リスト

head  
参照先
ノードA head
.data
A
head
.next
 
参照先
ノードB head
.next
.data
B
head
.next
.next
 

線形リストのノードは2個なので先頭ノードはノードA、末尾ノードはノードBです。

headの参照先であるノードAの後続ポインタhead.nextの参照先はノードBです。

ここでノードAのデータへの参照はhead.dataと表されます。

したがってノードAの後続ポインタhead.nextに参照されるノードBのデータはhead.next.dataと表されます。

ノードBは末尾ノードなので後続ポインタは存在しないので値はNoneとなります。

ノードBのデータはhead.next.dataなのでノードBの後続ポインタはhead.next.nextと表されます。

そのため以下の式が成立すればノードが2個の線形リストだと判断できます。

head.next.next is None

__len__メソッド

__len__メソッドでは線形リストのノード数を、noの値として返却します。

そのためノード数0、1、2個の判定はそれぞれno == 0、no == 1、no == 2という式で判定できるようになります。

ノードの探索search

def search(self, data: Any) -> int:
    """dataと等価なノードを探索"""
    cnt = 0
    ptr = self.head

    while ptr is not None:
        if ptr.data == data:
            self.current = ptr
            return cnt
        cnt += 1
        ptr = ptr.next
    return -1

searchメソッドでは引数で与えられたデータdataを線形リストから探索します。

探索方法は線形探索で、線形リストの先頭から順に探索します。

この探索における終了条件は次の2つがあります。

終了条件Ⅰ:等価なノードを見つけた。(探索成功)

終了条件Ⅱ:等価なノードが見つからず末尾ノードを通り越しそうになった。(探索失敗)

下の表ではノードCを探索する様子を表したものです。

head  
参照先
ノード A B C D
       
探索順        

走査中のノードを参照するptrをheadで初期化します。

なのでptrが参照しているのはheadの参照先の先頭ノードAになります。

先頭から何番目の要素を走査しているのかを表すカウンタ用変数cntを0で初期化します。

ptrの値がNoneでない間while文を実行して探索を続けます。

走査対象を次のノードに移動するためにptrに後続ポインタの参照先であるptr.nextを代入します。

それと同時にcntを1インクリメントすることで次のノードに移動したことを記録します。

cntの初期値は0(先頭)なので1増やすと2番目を表すことになります。

探索成功(終了条件Ⅰ)

走査中のノードのデータptr.dataの値と探索するdataが等しければ探索成功です。

見つけたのが何番目のノードであるかを知らせるためにcntの値を返却します。

探索失敗(終了条件Ⅱ)

ptrの値がNoneであれば、探索すべきノードがもう存在しないことになるので探索失敗となります。

while文を抜けて-1を返します。

ノードCを走査する過程でptrがどのように変化するのかを図示しました。

①ptr = head

head  
参照先
ノード A B C D
       
参照先            
ptr
の位置
             

ptrが参照しているのはノードA。

②ptr = ptr.next

head  
参照先
ノード A B C D
       
参照先            
ptr
の位置
             

ptrが参照しているのはノードB。

③ptr = ptr.next

head  
参照先
ノード A B C D
       
参照先            
ptr
の位置
             

ptrが参照しているのはノードC。



先頭へのノードの挿入add_first

def add_first(self, data: Any) -> None:
    """先頭にノードを挿入"""
    ptr = self.head  # 挿入前の先頭ノード
    self.head = self.current = Node(data, ptr)
    self.no += 1

add_firstメソッドでは線形リストの先頭にノードを挿入します。

下の表では図aのリストの先頭にノードXを挿入する様子を表したものです。

a head  
参照先
ノード A B C
     
位置 先頭
ノード
参照先   参照先 末尾
ノード
b head  
参照先
ノード X A B C
       
位置 先頭
ノード
ptr
参照先   参照先   参照先 末尾
ノード

まずptrに挿入前の先頭ノードAを参照するポインタを保存します。

次に挿入するノードXをNode(data, ptr)として生成します。

このときノードXのデータはdata、ptrはノードAを参照するポインタとなります。

こうすることでノードXの後続ポインタはptrつまりノードAを参照するようになります。

その結果としてノードXはheadとノードAの間に入ることになり線形リストの先頭ノードになります。

なおcurrentも挿入したノードXを参照するようになります。

最後にnoの値を1増やして線形リストのノード数を増やせば完了です。

末尾へのノードの挿入add_last

def add_last(self, data: Any):
    """末尾にノードを挿入"""
    if self.head is None:     # リストが空であれば
        self.add_first(data)  # 先頭に挿入
    else:
        ptr = self.head
        while ptr.next is not None:
            ptr = ptr.next
        ptr.next = self.current = Node(data, None)
        self.no += 1

add_lastメソッドでは線形リストの末尾にノードを挿入します。

ただしリストが空の場合は末尾かつ先頭にノードを挿入することになるので、メソッドadd_firstに挿入処理をさせます。

下の表ではリストが空でないときに図aのリストの末尾にノードXを挿入する様子を表したものです。

a head  
参照先
ノード A B C
     
位置 先頭
ノード
参照先   参照先 末尾
ノード
ptr
b head  
参照先
ノード A B C X
       
位置 先頭
ノード
参照先   参照先 ptr 参照先 末尾
ノード

まず挿入前の末尾ノードを見つけます。

ptrを先頭ノードを参照するように初期化し、後続ポインタの参照先を代入し続けることによって先頭から末尾まで移動させます。

その移動中にptr.nextつまり後続ポインタの参照先の値がNoneであればwhile文を抜けます。

後続ポインタの参照先の値がNoneということは後ろにノードが存在しないということなのでこのノードが末尾ノードです。

図aの場合はptrの参照先はノードCとなり、これが末尾ノードだと判定されます。

次に挿入するノードXをNode(data, None)として生成します。

後続ポインタをNoneとすることでノードXの後続ポインタはどのノードも参照しなくなります。

そしてノードC(ptr)の後続ポインタptr.nextの参照先を挿入するノードXを参照するようにします。

その結果としてノードXはノードCの後ろに入ることになり線形リストの末尾ノードになります。

最後にnoの値を1増やして線形リストのノード数を増やせば完了です。

先頭ノードの削除remove_first

def remove_first(self) -> None:
    """先頭ノードを削除"""
    if self.head is not None:  # リストが空でなければ
        self.head = self.current = self.head.next
    self.no -= 1

remove_firstメソッドでは線形リストの先頭ノードを削除します。

ただし削除を行うのはリストが空でないときで、空のときは何もしません。

下の表では図aのリストの先頭ノードAを削除する様子を表したものです。

a head  
参照先
ノード A B C
     
位置 先頭
ノード
参照先   参照先 末尾
ノード
b head  
参照先
ノード B C
   
位置 先頭
ノード
参照先 末尾
ノード

先頭ノードへの参照であるheadを、先頭から2番目にあるノードBへの参照であるhead.nextを代入します。

するとheadの参照先はノードAからノードBに変更されます。

その結果ノードAがどこからも参照されなくなり、ノードBが線形リストの先頭となります。

最後にnoの値を1減らして線形リストのノード数を減らせば完了です。

remove_firstメソッドはリストのノードが1個でも問題なく処理されます。

削除するノードは先頭ノードでも末尾ノードでもあるため、その後続ポインタhead.nextの値はNoneです。

なのでheadにNoneが代入されてリストは空になります。

末尾ノードの削除remove_last

def remove_last(self):
    """末尾ノードを削除"""
    if self.head is not None:
        if self.head.next is None: # ノードが1個だけであれば
            self.remove_first()    # 先頭ノードを削除
        else:
            ptr = self.head        # 走査中のノード
            pre = self.head        # 走査中のノードの先行ノード

            while ptr.next is not None:
                pre = ptr
                ptr = ptr.next
            pre.next = None        # preは削除後の末尾ノード
            self.current = pre
            self.no -= 1

remove_lastメソッドでは線形リストの末尾ノードを削除します。

削除を行うのはリストが空でないときで、空のときは何もしません。

リストのノードが1個の場合は削除するのが末尾かつ先頭のノードなので、メソッドremove_firstに削除処理をさせます。

下の表ではリストのノードが2個以上のときに図aのリストの末尾ノードCを削除する様子を表したものです。

a head  
参照先
ノード A B C
     
位置 先頭
ノード
参照先 pre 参照先 末尾
ノード
ptr
b head  
参照先
ノード A B   削除
   
位置 先頭
ノード
参照先 末尾
ノード
pre
参照先 ptr

まず削除前の末尾ノードと末尾から2番目のノードを見つけます。

見つけ方はadd_lastとほぼ同じですが、走査中のノードptrの先行ノードを参照するpreが追加されます。

図aの場合はpreの参照先はノードB、ptrの参照先はノードCとなります。

次に末尾から2番目のノードpre(ノードB)の後続ポインタであるpre.nextの値をNoneにします。

こうすることでptr(ノードC)はどこからも参照されなくなります。

その結果としてpreの参照先ノードBが線形リストの末尾ノードになります。

最後にnoの値を1減らして線形リストのノード数を減らせば完了です。

ノードの削除remove

def remove(self, p: Node) -> None:
    """ノードpを削除"""
    if self.head is not None:
        if p is self.head:       # pが先頭ノードであれば
            self.remove_first()  # 先頭ノードを削除
        else:
            ptr = self.head

            while ptr.next is not p:
                ptr = ptr.next
                if ptr is None:
                    return       # ptrはリストに存在しない
            ptr.next = p.next
            self.current = ptr
            self.no -= 1

removeメソッドでは引数で与えられたノードpを線形リストから削除します。

削除を行うのはリストが空でないときで、なおかつノードpがリストに存在するときです。

pが先頭ノードの場合は、メソッドremove_firstに削除処理をさせます。

下の表ではpが先頭ノードでなくリスト上に存在するときに削除する様子を表したものです。

なお今回はpが参照するノードがノードCだとします。

a head  
参照先
ノード A B C D
       
位置 先頭
ノード
参照先 ptr 参照先 p 参照先 末尾
ノード
b head  
参照先
ノード A B D
     
位置 先頭
ノード
参照先 ptr 参照先 末尾
ノード

まず削除するノードpの先行ノードを見つけます。

ptrにheadの参照先(先頭ノード)を代入します。

while文ではptrの後続ポインタptr.nextの参照先がpと等しくなるまで先頭から走査します。

ただしptr.nextがNoneとなったときはリストを走査してpと等しいノードが見つからなかったのでreturn文で抜けます。

ptr.nextがpと等しくなるとwhile文は終了します。

このときptrはpと等しいノードの直前のノードを参照します。

図aの場合はptrの参照先はノードB、pの参照先はノードCとなります。

次にp(ノードC)の後続ポインタであるp.nextの値を、ptr(ノードB)の後続ポインタptr.nextに代入します。

こうすることでptr(ノードB)の後続ポインタの参照先はノードDになり、p(ノードC)はどこからも参照されなくなります。

その結果としてノードpは線形リストから削除されます。

最後にnoの値を1減らして線形リストのノード数を減らせば完了です。

着目ノードの削除remove_current_node

def remove_current_node(self) -> None:
    """着目ノードを削除"""
    self.remove(self.current)

remove_current_nodeメソッドでは現在着目しているノードを線形リストから削除します。

着目ポインタcurrentをremoveメソッドに引数として渡すことで削除させます。

なお削除後のcurrentの参照先は削除したノードの先行ノードに更新されます。

全ノードの削除clear

def clear(self) -> None:
    """全ノードを削除"""
    while self.head is not None: # 空になるまで
        self.remove_first()      # 先頭ノードを削除
    self.current = None
    self.no = 0

clearメソッドでは線形リストの全ノードを削除します。

線形リストが空(headがNone)になるまで先頭ノードを削除することで全ノードが削除されます。

最後にnoの値を0にして線形リストのノード数を0にすれば完了です。

着目ノードを一つ後方に進めるnext

def next(self) -> bool:
    """着目ノードを一つ後方に進める"""
    if self.current is None or self.current.next is None:
        return False             # 進めることができなかった
    self.current = self.current.next
    return True

nextメソッドでは着目ノードを一つ後方に進めます。

ただし進めるのはリストが空でなく、着目ノードの後続ノードが存在するときです。

currentに後続ポインタの参照先のcurrent.nextを代入することで一つ後方のノードを参照させます。

進めたときはTrueを、進めなかったときはFalseを返却します。

着目ノードの表示print_current_node

def print_current_node(self) -> None:
    """着目ノードを表示"""
    if self.current is None:
        print('着目ノードはありません。')
    else:
        print(self.current.data)

print_current_nodeメソッドでは着目ノードのデータcurrent.dataの表示をします。

ただし着目ノードが存在しない場合は「着目ノードはありません。」と表示します。

全ノードの表示print

def print(self) -> None:
    """全ノードを表示"""
    ptr = self.head

    while ptr is not None:
        print(ptr.data)
        ptr = ptr.next

printメソッドでは線形リストの全ノードを表示します。

ptrを使って先頭から末尾までの各ノードのデータであるptr.dataをprint関数で表示します。

線形リスト(連結リスト)のプログラムは以下の通りです。



線形リスト(連結リスト)のプログラム

# 線形リスト

from __future__ import annotations
from typing import Any, Type

class Node:
    """線形リスト用ノードクラス"""

    def __init__(self, data: Any = None, next: Node = None):
        """初期化"""
        self.data = data  # データ
        self.next = next  # 後続ポインタ

class LinkedList:
    """線形リストクラス"""

    def __init__(self) -> None:
        """初期化"""
        self.no = 0          # ノードの個数
        self.head = None     # 先頭ノードへの参照
        self.current = None  # 着目ノードへの参照

    def __len__(self) -> int:
        """線形リスト上のノード数を返却"""
        return self.no

    def search(self, data: Any) -> int:
        """dataと等価なノードを探索"""
        cnt = 0
        ptr = self.head

        while ptr is not None:
            if ptr.data == data:
                self.current = ptr
                return cnt
            cnt += 1
            ptr = ptr.next
        return -1

    def add_first(self, data: Any) -> None:
        """先頭にノードを挿入"""
        ptr = self.head  # 挿入前の先頭ノード
        self.head = self.current = Node(data, ptr)
        self.no += 1

    def add_last(self, data: Any):
        """末尾にノードを挿入"""
        if self.head is None:     # リストが空であれば
            self.add_first(data)  # 先頭に挿入
        else:
            ptr = self.head
            while ptr.next is not None:
                ptr = ptr.next
            ptr.next = self.current = Node(data, None)
            self.no += 1

    def remove_first(self) -> None:
        """先頭ノードを削除"""
        if self.head is not None:  # リストが空でなければ
            self.head = self.current = self.head.next
        self.no -= 1

    def remove_last(self):
        """末尾ノードを削除"""
        if self.head is not None:
            if self.head.next is None: # ノードが1個だけであれば
                self.remove_first()    # 先頭ノードを削除
            else:
                ptr = self.head        # 走査中のノード
                pre = self.head        # 走査中のノードの先行ノード

                while ptr.next is not None:
                    pre = ptr
                    ptr = ptr.next
                pre.next = None        # preは削除後の末尾ノード
                self.current = pre
                self.no -= 1

    def remove(self, p: Node) -> None:
        """ノードpを削除"""
        if self.head is not None:
            if p is self.head:       # pが先頭ノードであれば
                self.remove_first()  # 先頭ノードを削除
            else:
                ptr = self.head

                while ptr.next is not p:
                    ptr = ptr.next
                    if ptr is None:
                        return       # ptrはリストに存在しない
                ptr.next = p.next
                self.current = ptr
                self.no -= 1

    def remove_current_node(self) -> None:
        """着目ノードを削除"""
        self.remove(self.current)

    def clear(self) -> None:
        """全ノードを削除"""
        while self.head is not None: # 空になるまで
            self.remove_first()      # 先頭ノードを削除
        self.current = None
        self.no = 0

    def next(self) -> bool:
        """着目ノードを一つ後方に進める"""
        if self.current is None or self.current.next is None:
            return False             # 進めることができなかった
        self.current = self.current.next
        return True

    def print_current_node(self) -> None:
        """着目ノードを表示"""
        if self.current is None:
            print('着目ノードはありません。')
        else:
            print(self.current.data)


    def print(self) -> None:
        """全ノードを表示"""
        ptr = self.head

        while ptr is not None:
            print(ptr.data)
            ptr = ptr.next

このプログラムは「linked_list.py」という名前で保存してください。

線形リスト(連結リスト)を利用するプログラム

コード例

# 線形リストクラスLinkedListの利用例

from enum import Enum
from linked_list import LinkedList

Menu = Enum('Menu', ['先頭に挿入', '末尾に挿入', '先頭を削除', '末尾を削除',
                     '着目を表示', '着目を進める', '着目を削除', '全削除',
                     '探索', '全ノードを表示', '終了'])

def select_Menu() -> Menu:
    """メニュー選択"""
    s = [f'({m.value}){m.name}' for m in Menu]

    while True:
        print(*s, sep=' ', end='')
        n = int(input(' : '))
        if 1 <= n <= len(Menu):
            return Menu(n)


lst = LinkedList()                    # 線形リストを生成

while True:
    menu = select_Menu()              # メニュー選択

    if menu == Menu.先頭に挿入:       # 先頭に挿入
        lst.add_first(int(input('値 : ')))

    elif menu == Menu.末尾に挿入:     # 末尾に挿入
        lst.add_last(int(input('値 : ')))

    elif menu == Menu.先頭を削除:     # 先頭を削除
        lst.remove_first()

    elif menu == Menu.末尾を削除:     # 末尾を削除
        lst.remove_last()

    elif menu == Menu.着目を表示:     # 着目を表示
        lst.print_current_node()

    elif menu == Menu.着目を進める:   # 着目を進める
        lst.next()

    elif menu == Menu.着目を削除:     # 着目を削除
        lst.remove_current_node()

    elif menu == Menu.全削除:         # 全削除
        lst.clear()

    elif menu == Menu.探索:           # 探索
        pos = lst.search(int(input('値 : ')))
        if pos >= 0:
            print(f'その値は{pos + 1}番目にあります。')
        else:
            print('その値は存在しません。')

    elif menu == Menu.全ノードを表示: # 全ノードを表示
        lst.print()

    else:                             # 終了
        break

実行結果

(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 1
値 : 3
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 2
値 : 4
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 1
値 : 2
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 2
値 : 5
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 1
値 : 1
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 10
1
2
3
4
5
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 4
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 9
値 : 5
その値は存在しません。
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 9
値 : 3
その値は3番目にあります。
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 3
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 10
2
3
4
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 9
値 : 1
その値は存在しません。
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 5
2
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 6
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 7
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 10
2
4
(1)先頭に挿入 (2)末尾に挿入 (3)先頭を削除 (4)末尾を削除 (5)着目を表示 (6)着目を進める (7)着目を削除 (8)全削除 (9)探索 (10)全ノードを表示 (11)終了 : 11

このプログラムは「linked_list_test.py」という名前で「linked_list.py」と同じフォルダに保存してください。