こんにちは。Yuinaです🌸
今日は双方向のアルゴリズムを理解すべく、Pythonで音楽プレイヤー風コードを作成しました。
コメントもたくさん書いたので、一緒に仕組みを理解できたら嬉しいです。
よろしくお願いいたします!
双方向リストとは…
双方向リストとは、リストの各要素(ノード)が 「次」と「前」の要素への参照(ポインタ)を持つ データ構造で、リストを先頭から末尾まで、または末尾から先頭まで、どちらの方向にもたどることができます。(ai参照)
作成したコードはこちら!
# 音楽プレイヤーリストのノードを定義するクラス
class SongNode:
def __init__(self,title):
self.title = title
self.prev = None
self.next = None
# 音楽プレイヤーリストを操作するクラス
class MusicPlayerList:
def __init__(self):
self.head = None
self.tail = None
# 曲を追加する
def add_song(self,title):
new_song = SongNode(title)
#先頭が存在しない
if self.head is None:
#先頭に追加
self.head = new_song
#ノードが1つしかないので、末尾もnew_song
self.tail = new_song
print(f"'{title}'をリストに追加しました。")
return
# 末尾に新しいノードを追加
new_song.prev = self.tail
self.tail.next = new_song
self.tail = new_song
print(f"'{title}'をリストに追加しました")
# 曲を削除する
def delete_song(self,title):
# ポインタを初期化
current_node = self.head
# プレイリストを先頭から順に検索する
while current_node is not None:
# 削除する曲が見つかったら
if current_node.title == title:
# 前のノードのnextポインタを更新
# 削除対象のノードの前に、
# 別のノードが存在するのかどうか
if current_node.prev is not None:
#current_nodeをリストから切り離す
current_node.prev.next = current_node.next
else:
# 削除対象が先頭ノードの場合,
# headをcurrent_nodeの次のノードに更新
self.head = current_node.next
# 次のノードのprevポインタを更新
if current_node.next is not None:
# 削除対象ノードを迂回して、前後のノードを繋ぐ
current_node.next.prev = current_node.prev
else:
# 削除対象が末尾ノードの場合、tailを前のノードに更新
self.tail = current_node.prev
"""
[ノードA] <== [ノードB] ==> [ノードC]
ノードA.nextをノードCに設定します。
ノードA ===> ノードC
逆方向のリンクを修正:
ノードC.prev = ノードA
->ノードBはリストから切り離される。
"""
print(f"'{title}'をリストから削除しました。")
return
# 曲が見つからなければ、次のノードへ移動
current_node = current_node.next
# リストの最後まで検索したが、曲が見つからなかった場合
print(f"リストに'{title}'という曲は見つかりませんでした。")
def play_list(self):
if self.head is None:
print("リストは空です。再生する曲がありません。")
return
print("---プレイリスト再生---")
current_song = self.head
song_number = 1
while current_song:
print(f"{song_number}.{current_song.title}")
current_song = current_song.next
song_number += 1
print("------------------")
if __name__ == "__main__":
player = MusicPlayerList()
player.add_song("YOASOBI - アイドル")
player.add_song("Official髭男dism - Subtitle")
player.delete_song("YOASOBI - アイドル")
player.play_list()
player.delete_song("YOASOBI - アイドル")
player.delete_song("Official髭男dism - Subtitle")
player.play_list()
出力結果はこのようになりました。

まとめ
今回は双方向リストのコードを作成しました。
もう少し理解が深まったら、山手線をテーマに双方向リスト書いてみたいと思います。
ありがとうございました✨