{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Deque" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [], "source": [ "from collections import deque" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Deque stands for double-ended queue. Can be used for fast, O(1) FIFO/LIFO. Internally implemented using doubly-linked lists of fixed-length blocks.\n", "\n", "Deques can be created from another sequence." ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a\n", "g\n" ] } ], "source": [ "d = deque('abcdefg')\n", "\n", "print(d[0])\n", "print(d[-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can extend a deque instance with another sequence either at the end or beginning" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "deque(['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'])\n" ] } ], "source": [ "d.extend('hij')\n", "d.extendleft('zyx')\n", "\n", "print(d)" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "deque(['w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'])\n" ] } ], "source": [ "d.append('k')\n", "d.appendleft('w')\n", "\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Can remove items from either ends using `pop` and `popleft`" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Popped rightmost item: d\n", "Popped left most item: a\n" ] } ], "source": [ "d = deque('abcd')\n", "\n", "print(\"Popped rightmost item:\", d.pop())\n", "print(\"Popped left most item:\", d.popleft())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Identical items can be removed using `.remove()`" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "deque(['b', 'c', 'd'])\n" ] } ], "source": [ "d = deque('abcd')\n", "\n", "d.remove('a')\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Raises `IndexError` if nothing left to remove" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "d c b a " ] } ], "source": [ "s = deque('abcd')\n", "\n", "while True:\n", " try:\n", " print(s.pop(), end=\" \")\n", " except IndexError:\n", " break" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "⭐️ Rotate a given collection" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "deque(['c', 'd', 'a', 'b'])\n", "deque(['a', 'b', 'c', 'd'])\n" ] } ], "source": [ "d = deque('abcd')\n", "\n", "d.rotate(2)\n", "print(d)\n", "\n", "d.rotate(-2)\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "⭐️ Deque size can be constrained using `maxlen`. Useful when dealing with streams of values but we just need to keep latest `n` items" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Left deque: deque([4, 3, 2], maxlen=3)\n", "Right deque: deque([2, 3, 4], maxlen=3)\n" ] } ], "source": [ "import random\n", "\n", "ld = deque(maxlen=3)\n", "rd = deque(maxlen=3)\n", "\n", "for i in range(5):\n", " ld.appendleft(i)\n", " rd.append(i)\n", "\n", "print(\"Left deque:\", ld)\n", "print(\"Right deque:\", rd)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Deque is thread-safe, so can be consumed from both ends at same-time." ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Left: 0\n", " Right: 4\n", " Left: 1\n", " Right: 3\n", " Left: 2\n", " Right: Done\n", " Left: Done\n" ] } ], "source": [ "import threading\n", "import time\n", "\n", "items = deque(range(5))\n", "\n", "def consume(direction, get_next):\n", " while True:\n", " try:\n", " next = get_next()\n", " print(f\"{direction:>8}: {next}\")\n", " time.sleep(0.1)\n", " except IndexError:\n", " break\n", " \n", " print(f\"{direction:>8}: Done\")\n", "\n", "left = threading.Thread(target=consume, args=('Left', items.popleft))\n", "right = threading.Thread(target=consume, args=('Right', items.pop))\n", "\n", "left.start()\n", "right.start()\n", "\n", "left.join()\n", "right.join()\n" ] } ], "metadata": { "interpreter": { "hash": "9e0fd7424d8281b91a098a189d6ae37333be9d5a00ec75c9d3dec88c73652714" }, "kernelspec": { "display_name": "Python 3.10.1 ('leetcode-yPz04C5d')", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.1" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }