Pythonでバイナリツリーのノードを削除する方法

スポンサーリンク

二分木と二分探索木については、以前の記事ですでに説明しました。

今回は、メモリリークを起こさずにバイナリツリーを削除するアルゴリズムを定式化します。

また、そのアルゴリズムをPythonで実装します。

スポンサーリンク

メモリリークとは?

プログラム中のメモリーリークは、変数にメモリーを割り当てた後、それを削除し忘れると発生します。

メモリリークが発生すると、プログラムの終了時に問題が発生することがあります。

そのため、メモリへの参照を削除する前に、割り当てを削除する必要があります。

Pythonはこれらのエラーをガベージコレクションの手続きで処理しますが、プログラム中にメモリリークを引き起こすようなコードを書かないように注意する必要があります。

ここでは、メモリリークを発生させずにバイナリツリー全体を削除するアルゴリズムについて説明します。

How to delete nodes of binary tree without memory leak?

二分木の要素を削除するには、del文を使って、各ノードに割り当てられたメモリを解放すればよい。

また、メモリリークを防ぐために、ノードそのものを削除する前に、そのノードの子ノードを削除する必要があります。

こうすることで、あるノードを参照している変数が、メモリを解放する前に削除されることがないようにすることができます

木構造全体の探索には、木構造探索アルゴリズム(in-order, pre-order, level-order, post-order など)を使用することができる。

しかし、メモリリークを避けるために、親ノードより先に子ノードを削除する必要があるため、親ノードより先に子ノードを走査する必要があります。

後順序木探索アルゴリズムでは、親ノードを訪れる前に、任意のノードの子ノードを探索します。

そこで、二分木を削除するアルゴリズムを実装するために、後順序木探索を使用することにします。

次節では、このアルゴリズムを実装するために、後順序木探索アルゴリズムを修正します。

バイナリツリーを削除するアルゴリズム

上述したように、2分木を削除するアルゴリズムは、以下のように定式化される。

  1. ルートから開始します。
    1. 現在のノードがNoneかどうかをチェックし、Noneの場合、戻る。そうでなければ3.に進む。
    1. 現在のノードの左側の子ノードを再帰的に削除します。
    1. 現在のノードの右の子を再帰的に削除します。
  2. 現在のノードを削除します。

Pythonでバイナリツリーを削除する

二分木を削除するアルゴリズムについて説明し、定式化しましたので、Pythonで実装します。

また、以下の画像で与えられた二分木に対してアルゴリズムを実行します。

出力では、各ノードが親の削除の前に削除されていることが確認できます。

from queue import Queue
 
 
class BinaryTreeNode:
    def __init__(self, data):
        self.data = data
        self.leftChild = None
        self.rightChild = None
 
 
def insert(root, newValue):
    # if binary search tree is empty, make a new node and declare it as root
    if root is None:
        root = BinaryTreeNode(newValue)
        return root
    # binary search tree is not empty, so we will insert it into the tree
    # if newValue is less than value of data in root, add it to left subtree and proceed recursively
    if newValue < root.data:
        root.leftChild = insert(root.leftChild, newValue)
    else:
        # if newValue is greater than value of data in root, add it to right subtree and proceed recursively
        root.rightChild = insert(root.rightChild, newValue)
    return root
 
 
def deleteTree(root):
    if root:
        # delete left subtree
        deleteTree(root.leftChild)
        # delete right subtree
        deleteTree(root.rightChild)
        # traverse root
        print("Deleting Node:", root.data)
        del root
 
 
root = insert(None, 15)
insert(root, 10)
insert(root, 25)
insert(root, 6)
insert(root, 14)
insert(root, 20)
insert(root, 60)
print("deleting all the elements of the binary tree.")
deleteTree(root)

コード

deleting all the elements of the binary tree.
Deleting Node: 6
Deleting Node: 14
Deleting Node: 10
Deleting Node: 20
Deleting Node: 60
Deleting Node: 25
Deleting Node: 15

結果は、以下の通りになります。

Delete a Binary Tree
Binary tree

まとめ

今回は、修正後順序木探索アルゴリズムを使って二分木を削除するアルゴリズムについて説明しました。

Pythonで様々なアルゴリズムを実装するための記事を今後も続けていきます。

タイトルとURLをコピーしました