Python 循環バッファ

Zeeshan Afridi 2023年6月21日
  1. Python での効率的な循環バッファー
  2. Python で循環バッファーを実装する
  3. Python 循環バッファの利点
  4. Python 循環バッファーの欠点
  5. まとめ
Python 循環バッファ

循環バッファーは、リング バッファーの別名です。 バッファーは、エンドツーエンドで接続されているかのように、単一の固定サイズのバッファーを使用するデータ構造です。

この構造は、データ ストリームを管理するのに役立ちます。一方の端で新しいデータを常に追加し、もう一方の端から古いデータを削除できます。 バッファがいっぱいになると、新しいデータが最も古いデータを上書きします。

Python での効率的な循環バッファー

効率的な循環バッファーは、データの効率的な挿入と削除を可能にするデータ構造です。

循環バッファは通常、配列として実装されます。 配列のヘッド ポインターは最初の要素を指し、テール ポインターは配列の最後の要素を指します。

ヘッド ポインターとテール ポインターは、配列の末尾に到達するとラップ アラウンドします。 循環バッファーへの挿入は、ヘッド ポインターをインクリメントし、その位置の配列にデータを書き込むことによって行われます。

循環バッファーからの削除は、テール ポインターをインクリメントすることによって行われます。 そのデータは配列から削除されませんが、ヘッド ポインターとテール ポインターは実質的にそれをスキップします。

循環バッファは、一定量のメモリしか必要としないため、効率的なデータ構造です。 実装も簡単です。

class Buffer:
    def __init__(self, size):
        self.data = [None for i in range(size)]

    def append(self, x):
        self.data.pop(0)
        self.data.append(x)

    def get(self):
        return self.data


buf = Buffer(4)
for i in range(10):
    buf.append(i)
    print(buf.get())

出力:

[None, None, None, 0]
[None, None, 0, 1]
[None, 0, 1, 2]
[0, 1, 2, 3]
[1, 2, 3, 4]
[2, 3, 4, 5]
[3, 4, 5, 6]
[4, 5, 6, 7]
[5, 6, 7, 8]
[6, 7, 8, 9]

Python で循環バッファーを実装する

Python で効率的な循環バッファーを実装する方法は多数あります。 一般的なアプローチの 1つは、キューの前と後ろの両方からの要素の削除と追加を効率的にサポートするように設計された collections.dequeue オブジェクトを使用することです。

もう 1つの方法は、リストを使用して、先頭と末尾のインデックスを別々に追跡することです。

どのアプローチが最適かを知りたい場合は、アプリケーション固有の要件によって異なります。 たとえば、要素を頻繁にバッファに追加および削除する必要があり、順序が重要でない場合は、dequeue アプローチが最適な場合があります。

一方、要素がバッファに 1 回だけ追加されてから何度も読み出される場合、または順序が重要な場合は、リスト アプローチの方が適している可能性があります。

Python で collections.enqueuecollections.dequeue を使用して循環キューを実装する

まず、関数 collections.enqueue を使用してキューに値を追加します。 次に、循環キューで collection.dequeue を使用して、キューから要素を削除できます。

その仕組みを理解するために、Python での循環キューの実際の例を見てみましょう。

コード例:

# implememting circular queue in python
class CircularQueue:
    def __init__(collections, k):
        collections.k = k
        collections.queue = [None] * k
        collections.head = collections.tail = -1

    # this function will insert (Enqueue) an element into the circular queue
    def enqueue1(collections, data):

        if (collections.tail + 1) % collections.k == collections.head:
            print("The queue is full\n")

        elif collections.head == -1:
            collections.head = 0
            collections.tail = 0
            collections.queue[collections.tail] = data
        else:
            collections.tail = (collections.tail + 1) % collections.k
            collections.queue[collections.tail] = data

    # this function will delete (dequeue) an element from the circular
    def dequeue1(collections):
        if collections.head == -1:
            print("The circular queue is empty\n")

        elif collections.head == collections.tail:
            temp = collections.queue[collections.head]
            collections.head = -1
            collections.tail = -1
            return temp
        else:
            temp = collections.queue[collections.head]
            collections.head = (collections.head + 1) % collections.k
            return temp

    # This function is used to print the queue
    def printCQueue1(collections):
        if collections.head == -1:
            print("Circular queue is empty")

        elif collections.tail >= collections.head:
            for i in range(collections.head, collections.tail + 1):
                print(collections.queue[i], end=" ")
            print()
        else:
            for i in range(collections.head, collections.k):
                print(collections.queue[i], end=" ")
            for i in range(0, collections.tail + 1):
                print(collections.queue[i], end=" ")
            print()


obj = CircularQueue(5)

# adding data to the queue
for i in range(1, 6):
    obj.enqueue1(i)

print("Display queue")
obj.printCQueue1()

# removing data from the queue
print("\nDelete Value:", obj.dequeue1())
print("Delete Value:", obj.dequeue1())


print("\nTwo values were deleted from the queue")
print("The new queue has 3 values now")
obj.printCQueue1()

出力:

Display queue
1 2 3 4 5

Delete Value: 1
Delete Value: 2

Two values were deleted from the queue
The new queue has 3 values now
3 4 5

Python 循環バッファの利点

Python でデータを操作するときに循環バッファーを使用すると、多くの利点があります。

  1. 1つの利点は、先入れ先出し (FIFO) 方式でデータを格納するために使用できることです。 これは、受信した元の順序でデータを処理する必要がある場合に役立ちます。
  2. もう 1つの利点は、循環バッファが後入れ先出し (LIFO) 方式でデータを格納できることです。 これは、受信した逆の順序でデータを処理する必要がある場合に適しています。
  3. さらに、ランダム アクセス方式でデータを格納するために循環バッファを使用できます。 これは、データにすばやくランダムにアクセスする必要がある場合に役立ちます。

Python 循環バッファーの欠点

Python で循環バッファーを使用することには、いくつかの欠点があります。

  1. まず、バッファ内の要素にランダムにアクセスすることはできません。 これにより、線形順序でないデータの操作が困難になる可能性があります。
  2. 次に、バッファのサイズが固定されています。 これは、バッファが保持できるよりも多くのデータを格納する必要がある場合に問題を引き起こす可能性があります。
  3. 最後に、循環バッファーは、他のデータ構造よりもデバッグが難しい場合があります。

まとめ

Python の循環バッファーは、データを格納するための高速で効率的な方法です。 循環データ バッファーは、1つのオブジェクトを保持するコンテナーとして使用できるキューです。

循環バッファは通常、ビデオ ゲームやオーディオ処理など、データが絶えず追加および削除される場合に使用されます。 1つのポインターで実装できますが、線形キューには 2つのポインターが必要です。

循環バッファは複数のキューに簡単に拡張できるため、同時データ アクセスが可能になります。

著者: Zeeshan Afridi
Zeeshan Afridi avatar Zeeshan Afridi avatar

Zeeshan is a detail oriented software engineer that helps companies and individuals make their lives and easier with software solutions.

LinkedIn