{ "cells": [ { "cell_type": "markdown", "id": "32afb885-4e17-4545-a33f-693837a78a10", "metadata": {}, "source": [ "### Size of the dynamic arrays used for lists in python" ] }, { "cell_type": "code", "execution_count": 12, "id": "06afcafb-1bf7-4172-aa5a-eeaed0724c9a", "metadata": {}, "outputs": [], "source": [ "# some utility classes\n", "\n", "class Empty(Exception):\n", " pass" ] }, { "cell_type": "code", "execution_count": 13, "id": "598bef80-29fd-4fd2-aa64-3a055fa0f455", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Array length: 0,Size in bytes: 56,Difference size in bytes: 56\n", "Array length: 1,Size in bytes: 88,Difference size in bytes: 32\n", "Array length: 2,Size in bytes: 88,Difference size in bytes: 0\n", "Array length: 3,Size in bytes: 88,Difference size in bytes: 0\n", "Array length: 4,Size in bytes: 88,Difference size in bytes: 0\n", "Array length: 5,Size in bytes: 120,Difference size in bytes: 32\n", "Array length: 6,Size in bytes: 120,Difference size in bytes: 0\n", "Array length: 7,Size in bytes: 120,Difference size in bytes: 0\n", "Array length: 8,Size in bytes: 120,Difference size in bytes: 0\n", "Array length: 9,Size in bytes: 184,Difference size in bytes: 64\n", "Array length: 10,Size in bytes: 184,Difference size in bytes: 0\n", "Array length: 11,Size in bytes: 184,Difference size in bytes: 0\n", "Array length: 12,Size in bytes: 184,Difference size in bytes: 0\n", "Array length: 13,Size in bytes: 184,Difference size in bytes: 0\n", "Array length: 14,Size in bytes: 184,Difference size in bytes: 0\n", "Array length: 15,Size in bytes: 184,Difference size in bytes: 0\n", "Array length: 16,Size in bytes: 184,Difference size in bytes: 0\n", "Array length: 17,Size in bytes: 248,Difference size in bytes: 64\n", "Array length: 18,Size in bytes: 248,Difference size in bytes: 0\n", "Array length: 19,Size in bytes: 248,Difference size in bytes: 0\n", "Array length: 20,Size in bytes: 248,Difference size in bytes: 0\n", "Array length: 21,Size in bytes: 248,Difference size in bytes: 0\n", "Array length: 22,Size in bytes: 248,Difference size in bytes: 0\n", "Array length: 23,Size in bytes: 248,Difference size in bytes: 0\n", "Array length: 24,Size in bytes: 248,Difference size in bytes: 0\n", "Array length: 25,Size in bytes: 312,Difference size in bytes: 64\n", "Array length: 26,Size in bytes: 312,Difference size in bytes: 0\n", "Array length: 27,Size in bytes: 312,Difference size in bytes: 0\n", "Array length: 28,Size in bytes: 312,Difference size in bytes: 0\n", "Array length: 29,Size in bytes: 312,Difference size in bytes: 0\n", "Array length: 30,Size in bytes: 312,Difference size in bytes: 0\n", "Array length: 31,Size in bytes: 312,Difference size in bytes: 0\n", "Array length: 32,Size in bytes: 312,Difference size in bytes: 0\n", "Array length: 33,Size in bytes: 376,Difference size in bytes: 64\n", "Array length: 34,Size in bytes: 376,Difference size in bytes: 0\n", "Array length: 35,Size in bytes: 376,Difference size in bytes: 0\n", "Array length: 36,Size in bytes: 376,Difference size in bytes: 0\n", "Array length: 37,Size in bytes: 376,Difference size in bytes: 0\n", "Array length: 38,Size in bytes: 376,Difference size in bytes: 0\n", "Array length: 39,Size in bytes: 376,Difference size in bytes: 0\n", "Array length: 40,Size in bytes: 376,Difference size in bytes: 0\n", "Array length: 41,Size in bytes: 472,Difference size in bytes: 96\n", "Array length: 42,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 43,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 44,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 45,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 46,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 47,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 48,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 49,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 50,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 51,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 52,Size in bytes: 472,Difference size in bytes: 0\n", "Array length: 53,Size in bytes: 568,Difference size in bytes: 96\n", "Array length: 54,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 55,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 56,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 57,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 58,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 59,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 60,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 61,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 62,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 63,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 64,Size in bytes: 568,Difference size in bytes: 0\n", "Array length: 65,Size in bytes: 664,Difference size in bytes: 96\n", "Array length: 66,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 67,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 68,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 69,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 70,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 71,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 72,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 73,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 74,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 75,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 76,Size in bytes: 664,Difference size in bytes: 0\n", "Array length: 77,Size in bytes: 792,Difference size in bytes: 128\n", "Array length: 78,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 79,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 80,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 81,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 82,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 83,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 84,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 85,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 86,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 87,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 88,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 89,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 90,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 91,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 92,Size in bytes: 792,Difference size in bytes: 0\n", "Array length: 93,Size in bytes: 920,Difference size in bytes: 128\n", "Array length: 94,Size in bytes: 920,Difference size in bytes: 0\n", "Array length: 95,Size in bytes: 920,Difference size in bytes: 0\n", "Array length: 96,Size in bytes: 920,Difference size in bytes: 0\n", "Array length: 97,Size in bytes: 920,Difference size in bytes: 0\n", "Array length: 98,Size in bytes: 920,Difference size in bytes: 0\n", "Array length: 99,Size in bytes: 920,Difference size in bytes: 0\n" ] } ], "source": [ "import sys\n", "\n", "data = []\n", "n = 100\n", "old_size = 0\n", "for i in range(n):\n", " print(f'Array length: {len(data)},'\n", " f'Size in bytes: {sys.getsizeof(data)},'\n", " f'Difference size in bytes: {sys.getsizeof(data) - old_size}')\n", " old_size = sys.getsizeof(data)\n", " data.append(1)" ] }, { "cell_type": "markdown", "id": "943f6eb2-c75c-422f-ad28-58670551e113", "metadata": {}, "source": [ "### Growing dynamic arrays by doubling the size" ] }, { "cell_type": "code", "execution_count": 14, "id": "2b308e94-8d86-4e2b-bec4-5fff436cc28c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 4, 8, 16]\n", "[1, 2, 1, 4, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 16]\n" ] }, { "data": { "text/plain": [ "Text(0, 0.5, 'Number of operations')" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAHHCAYAAABKudlQAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAASNdJREFUeJzt3QeUFFUe7/E/OYOAICAIKjlLMBLXAIhElbAoCBjWRBSQdUkmwICIIphR17gKSHgSVIIKqICgGAiKgAFBxSFJrnd+953q19MTmBm6e7rg+zmnYLq6u+6t/O8b6ubwPM8zAACAgMqZ3RkAAAA4EQQzAAAg0AhmAABAoBHMAACAQCOYAQAAgUYwAwAAAo1gBgAABBrBDAAACDSCGQAAEGgEM6eoxYsXW44cOeztt9+2IPjtt9/smmuusZIlS7p8T5w40U41N9xwg1WqVMlOJlqfq666KruzESijR49250AiadGihZtOBtOmTXPb98cff8zurCATCGbicFLkz5/ffv755xTv6+SvXbt2tuQtaAYOHGjz58+34cOH2yuvvGKtW7e2k9Evv/ziblZr1qzJ7qwAQGAQzMTBwYMHbdy4cdmdjUD78MMPrUOHDnbXXXfZddddZ9WrV7eTNZgZM2ZMqsHMs88+a+vXr8+WfCFx/Oc//7G///47u7Nx0rr++uvd9q1YsWJ2ZwWZQDATB/Xr13c3It2oTjX79u2LynJ27Nhhp512mgXNgQMH7NixY1FZVp48eSxfvnxRWRaiT2P2xiPIyJ07tyvtRWzkypXLbd/srspL79q5f//+uOYlCAhm4uDf//63HT169LilM6qj1Qmk6qlImq/qh8h68w0bNriSimLFilmpUqVsxIgR7qK6bds2V5JRtGhRK1OmjD366KOppql8KX/6TKFChax9+/buu5E+/fRTV7WjdAoWLGjNmze3Tz75JNln/Dx988039s9//tOKFy9uTZo0SXedf/jhB7v22mutRIkSbrkXXnihzZ07N0VVndZp8uTJ7u/jXWR0ERg8eLBVqFDB3fyrVatmjzzyiFtG5Da944477NVXX3Wf0QWsYcOGtnTp0hTLVDVhnz597IwzznDLrFWrlr3wwguptkN644033K/nM888063T7t277c8//3SlSnXq1LHChQu7/dKmTRtbu3Ztsu83btzY/d27d+/QuvrHQ2ptZjK7rjNnznRVm/46zJs3L9nn9uzZYwMGDHDp6DOlS5e2yy+/3FavXp3m9v7yyy/d8mfNmhWat2rVKjevQYMGyT6rdb7gggtSLOPjjz+2888/3+2Dc845x15++eUUn/nrr79c3vx1rVy5so0fPz5ZsOifQ9oGzzzzjJ177rnus9qun3/+eZrrELk+Or4LFChg5cuXt/vvv99efPHFFO0o/PY+qv5s1KiR+/zTTz+doeNa++f000+3QYMGheZpPRSw62aqdfVpHRXA7N27N802Mxndv/5xpvxqW2v7KM+ZaYfjb1etr/bZRx99lOx95VPXkv79+6f47k8//eTWb+zYscnOb11LtC10DdN3O3XqZDt37kz23Xfffdfatm1r5cqVc+unPNx3333uGpZa9b2/H7X9daz47QOXLFnijkHlX+fL+++/n6E2M++9955bXpEiRdz5q2PqtddeS3dbbdmyxW677TaXjtJTmz8dF5HL9tNU3vR5nXc69sLXR+dUs2bN3Promp3RbTJq1Cj3Qyhye8rNN9/sjjn96JKVK1daq1at3LGp/J599tnuuhcIHmLmxRdf1B3F+/zzz70+ffp4+fPn937++efQ+82bN/dq1aoVer1582b3eX0vkuaPGjUq9Fp/a179+vW97t27e0899ZTXtm1bN2/ChAletWrVvFtvvdXNv+SSS9z8JUuWhL6/aNEiN69OnTpe3bp13Xfuvvtul8eqVat6+/fvD332gw8+8PLmzetddNFF3qOPPuo99thj7jua9+mnn6bIU82aNb0OHTq4tCdPnpzm9tm+fbt3xhlneEWKFPHuuecel4d69ep5OXPm9KZPn+4+8/3333uvvPKKW+7ll1/u/taUlmPHjnn/+Mc/vBw5cng33nij9+STT3rt2rVz3x8wYECKbVq7dm3v9NNP9+69915v/PjxXsWKFb0CBQp4X331VbJ8li9f3qtQoYL73JQpU7z27du772tbRG5Trb/2i9Zn7Nix3r59+9wxcO6557pt/PTTT7vlnHnmmV6xYsVCx4TS0Xwt4+abbw6tq7aB9OrVy+Uvq+uqbVu2bFnvvvvu8yZOnOidc845XsGCBb3ff/899Ll//vOfbr8OGjTIe+6559w20TL/+9//prnNjx496p122mne4MGDQ/O0XbQfNSUlJYU+V7RoUe+uu+4KfU7ro2NVx8G///1vtw4NGjRw67Ru3brQ57QNdcyVLFnSfW7q1Klez5493ef69++f4hw677zzvMqVK7v8P/TQQ24fax8eOnTIS89PP/3klShRwqUzZswY75FHHvGqV6/utp2Wq+WH511pFC9e3O1X5UnHQEaOa9Ex1LBhw9DrL774wqWhz82ZMyc0X+d1o0aNUpxnWdm/q1ev9vLly+dVqlTJGzdunPfAAw945cqVC63f8eiY0Ocuvvhib9KkSe44075XWrqe+Xr06OG2wZEjR5J9X/tC+2zLli3JrpHaXzqWn3jiCXcc5cqVy+vSpUuy73bs2NHNe/jhh905eO2117rvhh9PonxonXS+DhkyxC1T56SW+cYbb3hlypTxRo8e7baRfw7u3r079H0/T+H7WvOUb10vtM10XdM5d/3116e7vf73v/+5bTty5EjvmWeecceujhcdOzqmI9NUPpV/5Vn7x18f5blUqVLenXfe6a4fM2fOzPA22bhxo5unZYY7ePCgy4vuTfLbb7+517r+a3nPPvusO35r1KjhBQHBTJyCGd2QcufO7fXr1y+qwYxuej5dOHTB1knnnwiya9cud4PWzTDyxquTOfxEfuutt9z8xx9/PHTDrFKliteqVSv3t0/Bztlnn+0CjMg8KbjKCF0I9fmPPvooNG/Pnj1uubrY6uYXvv633377cZepk1yfvf/++5PNv+aaa9x22bRpU7Jlalq5cmVoni6yCug6deoUmte3b193kwi/KUi3bt3chdAP/Pxtqgt7eDAoBw4cSLY+/v7WjUUBjE/HSlrHQGQwk9l1VZASPm/t2rUpLnJan4xs50i64Z5//vmh1507d3aTbiDvvfde6Eaq9N59993Q57Q+mrd06dLQvB07drjtEh4c6QZdqFAhb8OGDcnSVRChNLZu3ZrsHFIw8ueff4Y+pzQ1f/bs2emuh24W2nYKLHx//PGHC3BSC2Y0b968eVk6rnXDUN7980/BgZap7Ths2LBkgeLAgQOPG8xkZP8qMFWAE/6jSjc7XZuOF8woECxdurQL1HUj9Okmre+GBzPz58938/x971NAGv45/xp52WWXJbu+aH21bf7666/QvMhzSm655Ra3Pjq/fFq+lvnaa6+F5n333XehQHHFihUp8hl+vkUGM8qDAtMLLrjA+/vvv5OlH57n1KSW5+XLl7vlv/zyyynSbNKkSYoA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69evd39Xq1bNSpUqldVFAQAAxK8BsAaY7NOnj5UtW9aaNWvmpnLlylnfvn1t//79Wc8JAABAPIKZQYMG2ZIlS2z27Nn2119/uendd99189TTCQAAIKGrmd555x17++23Q6Nlix6gV6BAAevSpYtNmTIl2nkEAACIXsmMqpLOOOOMFPNLly5NNRMAAEj8YOaiiy6yUaNG2YEDB0Lz/v77bxszZox7DwAAIKGrmfT031atWln58uWtXr16bt7atWstf/78Nn/+/FjkEQAAIHrBjEbK3rhxo7366qv23XffuXndu3e3Hj16uHYzAAAACf+cmYIFC9pNN90U/dwAAADEIpiZNWuWtWnTxo3DpL/T0759+8zmAQAAILbBTMeOHW379u2ux5L+TkuOHDns6NGjWc8NAABALIKZY8eOpfo3AABA4Lpmv/zyy3bw4MEU8w8dOuTeAwAASOhgpnfv3paUlJRi/p49e9x7AAAACR3MeJ7n2sZE+umnn6xYsWLRyhcAAEB0u2afd955LojRdOmll1ru3P//q2r0u3nzZmvdunVGFwcAABDfYMbvxbRmzRr3BODChQuH3subN69VqlTJrr766ujkCgAAINrBjMZjEgUtXbt2dcMXAAAABO4JwL169YpNTgAAAOLRAFjtYx555BE7//zzrUyZMlaiRIlkU2YsXbrU2rVrZ+XKlXNtcWbOnJmisfHIkSOtbNmybtynyy67zI0LBQAAkOVgZsyYMTZhwgRX1aQu2oMGDbLOnTtbzpw5bfTo0Zla1r59+9zI25MnT071/YceesgmTZpkU6dOtU8//dQKFSrk2uscOHAgs9kGAAAnqUxXM2m07Geffdbatm3rgheNmH3uueda3bp1bcWKFdavX78ML0vjPWlKjUplJk6caP/5z3+sQ4cObp4eynfGGWe4Epxu3bplNusAAOAklOmSGY3RVKdOHfe3ejT5D9C76qqrbO7cuVHLmLp6Ky1VLfn0HJsLLrjAli9fHrV0AADAKRbMlC9f3n799Vf3t0pkFixY4P7+/PPPLV++fFHLmAIZUUlMOL3230uNhlrYvXt3sgkAAJy8Mh3MdOrUyT744AP395133mkjRoywKlWqWM+ePa1Pnz6W3caOHetKcPypQoUK2Z0lAACQSG1mxo0bF/pbjYArVqxoy5YtcwGNeiZFi3pKyW+//eZ6M/n0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gFh3zT5y5Ii98MIL9v7771vDhg2tUKFCyd7X2EkAAAAJG8ysW7fOGjRo4P7esGFDigfqAQAAJHQws2jRotjkBAAAIJ5dszdt2mTz58+3v//+2732PC+riwIAAIhfMPPHH3+47tlVq1a1K6+80n799Vc3v2/fvjZ48OCs5wQAACAewYwGmFQX7a1bt1rBggVD87t27Wrz5s3LSh4AAADi12ZmwYIFrnqpfPnyyeZXqVLFtmzZkvWcAAAAxKNkZt++fclKZHx//vmn5cuXLyt5AAAAiF8w07RpU3v55ZeTdcc+duyYPfTQQ9ayZcus5wQAACAe1UwKWtQAeOXKlXbo0CEbOnSoff31165k5pNPPslKHgAAAOJXMlO7dm33sLwmTZpYhw4dXLVT586d7YsvvrBzzz036zkBAACIR8mMFCtWzO65556sfBUAACD7g5ldu3a5wSa//fZb97pmzZrWu3dvK1GiRHRzBwAAEO1qpqVLl1qlSpVs0qRJLqjRpL/PPvts9x4AAEBCl8zcfvvt7gF5U6ZMsVy5crl5R48etdtuu82999VXX8UinwAAANEpmdGYTBq2wA9kRH8PGjTIvQcAAJDQwUyDBg1CbWXCaV69evWilS8AAIDoVTN9+eWXob/79etn/fv3d6UwF154oZu3YsUKmzx5so0bNy5jqQIAAMQzmKlfv7570q/neaF5elhepH/+85+uPQ0AAEBCBTObN2+OfU4AAABiFcxUrFgxK8sGAABIzIfm/fLLL/bxxx/bjh073CCT4dSmBgAAIGGDmWnTptktt9xiefPmtZIlS7q2ND79TTADAAASOpgZMWKEjRw50oYPH245c2a6ZzcAAEBUZToa2b9/v3Xr1i1ugczPP/9s1113nSsFKlCggNWpU8dWrlwZl7QBAEDiy3RE0rdvX/vf//5n8aBxny655BLLkyePvffee/bNN9/Yo48+asWLF49L+gAA4CSsZho7dqxdddVVNm/ePFdKokAj3IQJE6KWufHjx1uFChXsxRdfDM3TgJYAAAAnFMzMnz/fqlWr5l5HNgCOplmzZlmrVq3s2muvtSVLltiZZ57pBrS86aabopoOAAA4hYIZVfO88MILdsMNN1is/fDDD250bg1i+e9//9s+//xz11tKPal69eqV6ncOHjzoJt/u3btjnk8AABCgYCZfvnyuHUs86Bk2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jrfNI4M2tRfTttZxGMu0S5QoYWPGjLGrr77apacfa0OHDnWlU2qUG+v11vnVtWtXa9asmaviU/vE2bNnu/tL1MS0r1SALVq0yHUxi5zUvS2WUktT04svvujFmrrKqqtg3rx5vVKlSnmXXnqpt2DBAi+7xKtrtroNli1b1q23ukzq9aZNm7x4mT17tle7dm3XJbd69ereM888E7e058+f746v9evXe/G0e/dut2/POussL3/+/N4555zjukUfPHgwLum/+eabLk3tc3WPvv3221236HhfR9Q9e8SIEd4ZZ5zh9r/OuWjti+OlrWtKau/rUQWxTNvvCp7apO/FMu2///7b69Spk1euXDm373Xet2/f3nUNz477RjS7Zi9KJ209juCKK65w1/U8efK4dG+66SZv+/btMU/b9/zzz3uVK1d257sehTFz5kwvmnLon+iFRgAAAPFFmxkAABBoBDMAACDQCGYAAECgEcwAAIBAI5gBAACBRjADAAACjWAGAAAEGsEMgITz448/usH49BTRRPHdd9+5sXw0EKoGyssKPfFU66URygFED8EMcAL0GPY777zTDdqWL18+q1ChgntUf/h4O4lIN9SZM2dmdzYCRcNcaIgNPfY/0ffvyRpQAmlhbCbgBC72GihSo2w//PDDbvRnDaCncX80xpZ+yWeFHsqt8Woix0o6dOjQCY9bc6o7kW2o8Ww0GGc8BwEFkDGUzABZdNttt7lfrhocUgO4Va1a1Q2aOGjQIFuxYkWav25VxaB5/iBrftXDe++9Zw0bNnQlPB9//LG1aNHCjaCuwQhPP/300IBw69atcwOCFi5c2M444ww3Gq8GzPPpe/369XMDyWmgNw0sN3r06ND7lSpVcv936tTJpeu/juTnffr06W5wuIIFC1q9evVs+fLloc9ouZFVLhMnTky2zBtuuMENnKjBNJVfBX/33nuvHTlyxA1ApzyWL1/eDXgZSQGhBuJU1Y4GHF2yZEmy9zOyLVLbhqkNuKk8KR/a/lonDYbn03ZYtWqV+4z+Dt+ekcsZO3asGzRSA8Nqe7399tuWHu3rpk2bus+rZE/7bt++faH3tS01GGXPnj3deiqYmjVrlu3cudON8q15devWtZUrV2Z6udonGtxTA71qQMDwAU61DnLeeee5dda29I/X888/35VSaV8qoN+yZUu66wjEXFRHegJOEX/88YeXI0cO78EHH0z3c/6gel988UVo3q5du5INqucP0la3bl03sKcGudTyNdBm4cKFvSFDhnjfffedm/RdDRY3fPhw79tvv/VWr17tXX755V7Lli1Dy9f3ihYt6o0ePdrbsGGD99JLL7m8+oOG7tixIzR46a+//upep5d3DX45Z84cNwDiNddc4wapO3z4sPuMBiXUoHHhNHCePuPTYHNFihRxgzlqHTTgnJbbqlUr74EHHnB5vO+++9wAeNu2bUuWdvny5b23337b++abb7wbb7zRLef3338PbceMbIvIbZiaCRMmuG32+uuvu88MHTrU5Ud5E22nWrVqeYMHD3Z/79mzJ9Xl3H///W57zZs3z/v+++/dNtYAkosXL062r5V30b4uVKiQ22ZK65NPPvHOO+8874YbbggtU9uyRIkS3tSpU91nbr31VpfX1q1be2+99ZbbLx07dvRq1KjhBq7M7HInT57sbdy40Rs7dqyXM2fO0DbS4IvK6/vvv+/WWcek9nuxYsW8u+66y6Wh/TJt2jRvy5YtqW4PIF4IZoAs+PTTT92Ffvr06VELZiJHkdWNWDegcLrpa/TbcAoAwke+1veaNGmS7DONGzf2hg0bFnqtz8+YMSNDeX/uuedC877++ms3T8FDZoIZvT569GhoXrVq1bymTZuGXh85csTdfBVMhKc9bty40Gd0I1VwM378+Exti8htmBqNoqzAKnKb3XbbbaHXWs/0RpQ+cOCAV7BgQW/ZsmXJ5vft29fr3r17qsGM3rv55puTff6jjz5yQYVGeBZtu+uuuy70vgILLUOjbfuWL1/u5um9rC5XgVDp0qW9KVOmpHnsKqDRPD84AxIFbWaALIjFYPONGjVKMU/VTuHWrl1rixYtclULqbXpUFWXqNohXNmyZW3Hjh1Zylf4srQc0bKqV6+e4WWo+i1nzv9fq60qIVUb+XLlymUlS5ZMkceLLroo9LfaEGkbffvtt5naFpHbMNLu3bvtl19+cdUl4fRaaWTUpk2bbP/+/Xb55ZenaKejqprUaPlffvmlvfrqq8mOLVVXbd682WrUqJFiH2jbidpoRc7T9lO1YlaWq6okfTe940RVgqo2VHWd1vOyyy6zLl26hI4LILsQzABZUKVKFXfxP14jX/8GHh78qJFwatQG4Xjz9u7d63pLjR8/PsVnw28oefLkSfae8qobWVaEL0vLEX9ZWr/IwC619UstPyeax4xui9S2aywoPzJ37lw788wzk72ndjhpfeeWW25x7VkiqQ1Levsgvf2SleVmdB+obZOWqzZFb775pv3nP/+xhQsXum7rQHYhmAGyQL9Q9et08uTJ7sIeecNUI181jixVqpR7/euvv4Z+nZ9IV9cGDRrYO++84xpvRvZ2ygzdxNRj6kRp/dQ9XQGNf0ONZldeNaRu1qyZ+1sNhtUIVw16o7ktihYtauXKlbNPPvnEmjdvHpqv12romlE1a9Z0QcvWrVuTLSc9WodvvvnGKleunKW8x3K5fq+v1I4THcuahg8f7krPXnvtNYIZZCt6MwFZpEBGF3rd8HRT3bhxo6sCmTRpUqh6RD1JdJEfN26ce0+9cfRLNqvU5fvPP/+07t272+eff+6qU9QVvHfv3pkKThQA6FkpCkR27dqV5fyoh4t61Tz00EMuL9om6pUVLVrejBkzXAmY1l15Ve+baG4LUa8qlfCopEHPkbn77rtdUNa/f/8ML0M9gu666y4bOHCgvfTSSy4/q1evtieeeMK9Ts2wYcNs2bJlLkBTejqG3n333VDAllXRWG7p0qXd8asSmN9++82SkpJcFZUCGPVoUw+mBQsWuGX71VZAdiGYAbJID8rTzUrdlgcPHuzagKgdgYKEKVOmhD73wgsvuFIFtd1QF2F1s80qvwRBN+srrrjCtZvQMlUKFN4m5XgeffRRVzWgLrtptefICN3EnnrqKRd0qBuyuqnrhh4tCgI1adnqaqwuyepiHc1tISpdU5d67UctRzdwpaXqxMy47777bMSIEa57trZN69atXbWT3805ktqsKMDdsGGD60atfTFy5Ei3biciGstVaZcC86efftp9T93A1T1fgaX/KIKbb77ZBZWq0gKyUw61As7WHAAAAJwASmYAAECgEcwAAIBAI5gBAACBRjADAAACjWAGAAAEGsEMAAAINIIZAAAQaAQzAAAg0AhmAABAoBHMAACAQCOYAQAAgUYwAwAALMj+L+P2dtiKsJb1AAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import math\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "\n", "n = 16\n", "overflows = [2 ** i for i in range(1, int(math.log(n, 2) + 1))]\n", "print(overflows)\n", "\n", "operations = []\n", "for i in range(1, n + 1):\n", " if i in overflows:\n", " operations.append(i)\n", " else:\n", " operations.append(1)\n", "\n", "print(operations)\n", "sns.barplot(x=list(range(1, n+1)), y=operations)\n", "plt.title('Number of operations when growing dynamic arrays')\n", "plt.xlabel('Current number of elements')\n", "plt.ylabel('Number of operations')" ] }, { "cell_type": "markdown", "id": "cf04d1c1-e9df-428c-a70a-1ce766aadbe1", "metadata": {}, "source": [ "### Amortized cost of list operations" ] }, { "cell_type": "code", "execution_count": 15, "id": "5c3d237f-89c0-46ea-9cf7-dc43792a0a7d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "10\n", "100\n", "1000\n", "10000\n", "100000\n", "1000000\n", "[[1, np.float64(3.0556839192286134e-07), np.float64(4.5043451447079087e-07)], [10, np.float64(3.6393224339311326e-08), np.float64(1.4043414710009863e-08)], [100, np.float64(1.9638328618990878e-08), np.float64(1.5857606004925413e-09)], [1000, np.float64(2.0824966971607263e-08), np.float64(3.761772953682385e-10)], [10000, np.float64(2.1143759950064126e-08), np.float64(4.1826663573827645e-09)], [100000, np.float64(2.4833153336658146e-08), np.float64(3.355286019531847e-09)], [1000000, np.float64(2.519506110062745e-08), np.float64(2.616057498700928e-09)]]\n", "[ 1 10 100 1000 10000 100000 1000000]\n" ] }, { "data": { "text/plain": [ "Text(0, 0.5, 'time')" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAHLCAYAAADmwLMJAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAOCJJREFUeJzt3Qd8FGX+x/HfJiEJBBKaNAlVpPd22FEP/3eW0zsbpzS7hwU9TuVORT0Fz3KHZxdORMBy6qGengUFxUIHESyIhaKUUBMJkJDN/F+/J5lls9kku6TMk93Pm9ewu7OT3WefnZ39zjPPM+tzHMcRAAAACyV4XQAAAICyEFQAAIC1CCoAAMBaBBUAAGAtggoAALAWQQUAAFiLoAIAAKxFUAEAANYiqAAAAGsRVBBXPvjgA/H5fOayJp100klmihd79+6Vyy67TFq0aGHqe9y4cV4XSdavX2/K8sADD0isrcOjR4+Wdu3aeVquWBFvn9XagKCCqDz22GNmIzl48GCxvZzPPPOM18Ww3qRJk+TVV1+tlsfV+r/66qtl5syZMmLECKkp//vf/+SOO+4Q22iQsKlcX375pSmPBjjAZgQVRGX27Nlmg7tkyRL59ttvpbYFlRNOOEH2799vLlF9QWXevHnyi1/8QiZOnCgXX3yx9O/fX2oyqNx5550ST6ZOnSpr166NOqhoPRFUYDuCCiL2ww8/yKeffip///vf5YgjjjChxTb79u0r9/6EhARJTU01l6g+WVlZ0rBhQ6+LETfq1KkjKSkpXhcDqBZsrRExDSaNGjWS008/Xc4999ywQSW4H8Cjjz4qHTp0kHr16smwYcNk06ZNoj/W/de//lVat24tdevWld/85jeya9eusC0i3bt3NxvfVq1aydixY2XPnj0lltHjyD169JDly5ebFhJ9nj//+c+mxeeLL76QDz/80JRFJ/eYc+jxfW11cZcJnUKPU8+aNcu0DGi5GzduLBdeeKF5TaGeeuop6dixo1lu0KBB8tFHH0VVz/o8+nf6erS+9bW9++67UdfPunXr5He/+53pJ6LhTOtcy5ydnW3u19eYm5srM2bMCLxm7etQUQC59NJLpXnz5uYxe/fubf7e5davhto333wz8Ljl7bXr/ddcc41Znzp37mweV+t5wYIFgWXmz59vlpszZ06pv3/uuefMfQsXLjTl1/XOfVx3Kus90vobOHCgLF26NGyr0PHHHy9paWkmdOm6+tVXX5VYRg+d6ONr66I+ty6XkZEhY8aMqTA0Hzx40LRodOrUybzmJk2ayHHHHSdz586VaIXro/LCCy+YemzQoIGkp6dLz5495aGHHgqs9+edd565PnTo0EA9ldd36/PPPzfPo59pLa+uV5dccons3LkzbJ18/fXXcv7555vn1td2/fXXy4EDB6J+710//fSTeT5d9/R90/X/6aefLrGMu/79+9//lnvuuces8/qYp5xyStgW4Mp+VlEzkmroeRADdGPy29/+VpKTk2X48OHy+OOPmw28bujDLZufny/XXnutCSL33Xef2WidfPLJZmNy8803mw3Hww8/LOPHjy+xwdENnW7ATz31VNPHQZu03ef65JNPzN6jSzeSv/rVr8wXsB5i0I2YBgx93vr168tf/vIXs5zOD0dDgPahCLZhwwa59dZbpVmzZoF5utG77bbbzGvQTqLbt283Zde/X7lyZaD14F//+pdceeWVcswxx5gOpN9//72cddZZJthkZmZWWMf6uvX169/fddddpq4XL15svjQ17EVaP1r3p512muTl5Zm60C8V3dC/8cYbJtDol6m+bn0tuoG+4oorzGPrRrsseshM61bfN/1yad++vbz00kvmy0sfU7+Iunbtah73hhtuMF8Sf/zjH83fagtceTRUvvjii3LdddeZLyENYv/3f/9nDjFqGNXn1frT9eqcc84p8bc6T8s9ZMgQc3vz5s3myz70fQ0ONj///LN5n/RLTddNXa/1vXLXrffee8+sV/qlrPWtr13f72OPPVZWrFhRKhToeqH1MXnyZHP/tGnTzPrzt7/9rczXrI+ry7vvQU5Ojixbtsz8/S9/+UupDH39+hnVL2i3DBqydP3Q90nXW63rf/7znybc6/um3MuyHlPrSEOYrk+6M6Bf9Hq5aNGiUoFQ60TrSV+j3q/PtXv3bnn22Wejeu/Vtm3bzKFEN9jo+vTWW2+Z0Kz1FtpZ+9577zWtprpt0WCu7/FFF11kPkuuyn5WUYMcIALLli1zdHWZO3euuV1YWOi0bt3auf7660ss98MPP5jljjjiCGfPnj2B+RMmTDDze/fu7Rw8eDAwf/jw4U5ycrJz4MABczsrK8vcHjZsmOP3+wPLPfLII+bvn3766cC8E0880cx74oknSpW3e/fu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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import timeit\n", "import numpy as np\n", "import pandas as pd\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "def append_cost(n=100):\n", " data = []\n", " for i in range(n):\n", " data.append(None)\n", "\n", "\n", "ns = [1, 10, 100, 1000, 10000, 100000, 1000000]\n", "results = []\n", "for n in ns:\n", " print(n)\n", " time = np.array(timeit.repeat('append_cost(n)', globals=globals(), number=1, repeat=30))\n", " time /= n\n", " results.append([n, np.mean(time), np.std(time, ddof=1)])\n", "\n", "print(results)\n", "df = pd.DataFrame(results, columns=['n', 'time', 'error'])\n", "df.head() \n", "\n", "plot = sns.lineplot(data=df, x='n', y='time')\n", "plot.set(xscale='log')\n", "print(df.n.to_numpy())\n", "plt.errorbar(df.n.to_numpy(), df.time.to_numpy(), yerr=df.error.to_numpy())\n", "plt.title(\"Amortized cost of python's list append\")\n", "plt.xlabel('n')\n", "plt.ylabel('time')" ] }, { "cell_type": "markdown", "id": "ef6eb5fa-f1fe-4200-bf1d-bf65d3be8930", "metadata": {}, "source": [ "### Implementing stacks in python" ] }, { "cell_type": "code", "execution_count": 16, "id": "9d254a57-cf4e-4e18-9d7e-8aabcb67da41", "metadata": {}, "outputs": [], "source": [ "class Stack:\n", " \n", " \n", " def __init__(self):\n", " self._data = []\n", " \n", " \n", " def __len__(self):\n", " return len(self._data)\n", " \n", " \n", " def is_empty(self):\n", " return len(self._data) == 0\n", " \n", " \n", " def push(self, e):\n", " self._data.append(e)\n", " \n", " \n", " def top(self):\n", " if self.is_empty():\n", " raise Empty('Stack is empty')\n", " return self._data[-1]\n", " \n", " \n", " def pop(self):\n", " if self.is_empty():\n", " raise Empty('Stack is empty')\n", " return self._data.pop()\n", " \n", " \n", " def __str__(self):\n", " return f'{self._data}'" ] }, { "cell_type": "code", "execution_count": 17, "id": "07276fa7-ef33-4513-a946-694dc4a9d645", "metadata": {}, "outputs": [ { "ename": "Empty", "evalue": "Stack is empty", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mEmpty\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[17]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m s = Stack()\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m \u001b[43ms\u001b[49m\u001b[43m.\u001b[49m\u001b[43mpop\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# this will raise an exception, because the stack is empty\u001b[39;00m\n", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[16]\u001b[39m\u001b[32m, line 28\u001b[39m, in \u001b[36mStack.pop\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 26\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mpop\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[32m 27\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m.is_empty():\n\u001b[32m---> \u001b[39m\u001b[32m28\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m Empty(\u001b[33m'\u001b[39m\u001b[33mStack is empty\u001b[39m\u001b[33m'\u001b[39m)\n\u001b[32m 29\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m._data.pop()\n", "\u001b[31mEmpty\u001b[39m: Stack is empty" ] } ], "source": [ "s = Stack()\n", "s.pop() # this will raise an exception, because the stack is empty" ] }, { "cell_type": "code", "execution_count": null, "id": "414fa03e-35cc-454e-8c68-8b37c7e3d2fa", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Length: 2\n", "Pop: 3\n", "Empty: False\n", "Pop: 5\n", "Empty: True\n", "Top: 9\n", "Length: 3\n", "Pop: 4\n", "Stack: [7, 9, 6]\n" ] } ], "source": [ "s.push(5)\n", "s.push(3)\n", "print(f'Length: {len(s)}')\n", "print(f'Pop: {s.pop()}')\n", "print(f'Empty: {s.is_empty()}')\n", "print(f'Pop: {s.pop()}')\n", "print(f'Empty: {s.is_empty()}')\n", "s.push(7)\n", "s.push(9)\n", "print(f'Top: {s.top()}')\n", "s.push(4)\n", "print(f'Length: {len(s)}')\n", "print(f'Pop: {s.pop()}')\n", "s.push(6)\n", "print(f'Stack: {s}')" ] }, { "cell_type": "markdown", "id": "cbb9121c-6984-4d0b-a495-307a0d94bb58", "metadata": {}, "source": [ "### Implementing queues in python" ] }, { "cell_type": "code", "execution_count": null, "id": "ec927ec9-875e-46d2-930a-c4e70e3a5a36", "metadata": {}, "outputs": [], "source": [ "class Queue:\n", " \n", " \n", " DEFAULT_CAPACITY = 10\n", " \n", " \n", " def __init__(self):\n", " self._data = [None] * Queue.DEFAULT_CAPACITY\n", " self._size = 0\n", " self._front = 0\n", " \n", " \n", " def __len__(self):\n", " return self._size\n", " \n", " \n", " def is_empty(self):\n", " return self._size == 0\n", " \n", " \n", " def first(self):\n", " if self.is_empty():\n", " raise Empty('Queue is empty')\n", " return self._data[self._front]\n", " \n", " \n", " def dequeue(self):\n", " e = self.first()\n", " self._data[self._front] = None\n", " self._front = (self._front + 1) % len(self._data)\n", " self._size -= 1\n", " return e\n", " \n", " \n", " def enqueue(self, e):\n", " if self._size == len(self._data):\n", " self._resize(2 * len(self._data))\n", " back = (self._front + self._size) % len(self._data)\n", " self._data[back] = e\n", " self._size += 1\n", " \n", " \n", " def _resize(self, capacity):\n", " old = self._data\n", " self._data = [None] * capacity\n", " i = self._front\n", " for j in range(self._size):\n", " self._data[j] = old[i]\n", " i = (i + 1) % len(old)\n", " self._front = 0\n", " \n", " \n", " def __str__(self):\n", " return f'{self._data}'" ] }, { "cell_type": "code", "execution_count": null, "id": "815dcdea-96df-45d4-9538-5b0429d4bac1", "metadata": {}, "outputs": [ { "ename": "Empty", "evalue": "Queue is empty", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mEmpty\u001b[0m Traceback (most recent call last)", "Input \u001b[1;32mIn [11]\u001b[0m, in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m q \u001b[38;5;241m=\u001b[39m Queue()\n\u001b[1;32m----> 2\u001b[0m \u001b[43mq\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdequeue\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", "Input \u001b[1;32mIn [10]\u001b[0m, in \u001b[0;36mQueue.dequeue\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 27\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdequeue\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m---> 28\u001b[0m e \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfirst\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 29\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_data[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_front] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 30\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_front \u001b[38;5;241m=\u001b[39m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_front \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m) \u001b[38;5;241m%\u001b[39m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_data)\n", "Input \u001b[1;32mIn [10]\u001b[0m, in \u001b[0;36mQueue.first\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfirst\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m 22\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mis_empty():\n\u001b[1;32m---> 23\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m Empty(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mQueue is empty\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_data[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_front]\n", "\u001b[1;31mEmpty\u001b[0m: Queue is empty" ] } ], "source": [ "q = Queue()\n", "q.dequeue() # this will raise an exception, because the queue is empty" ] }, { "cell_type": "code", "execution_count": null, "id": "f1b2e403-5073-41cb-a94e-42581fbeb996", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Length: 2\n", "Dequeue: 5\n", "Empty: False\n", "Dequeue: 3\n", "Empty: True\n", "First: 7\n", "Length: 3\n", "Dequeue: 7\n", "Queue: [None, None, None, 9, 4, 6, None, None, None, None]\n" ] } ], "source": [ "q.enqueue(5)\n", "q.enqueue(3)\n", "print(f'Length: {len(q)}')\n", "print(f'Dequeue: {q.dequeue()}')\n", "print(f'Empty: {q.is_empty()}')\n", "print(f'Dequeue: {q.dequeue()}')\n", "print(f'Empty: {q.is_empty()}')\n", "q.enqueue(7)\n", "q.enqueue(9)\n", "print(f'First: {q.first()}')\n", "q.enqueue(4)\n", "print(f'Length: {len(q)}')\n", "print(f'Dequeue: {q.dequeue()}')\n", "q.enqueue(6)\n", "print(f'Queue: {q}')" ] }, { "cell_type": "markdown", "id": "f77cf609-3f9c-4a67-8efa-98d36212d7f1", "metadata": {}, "source": [ "### Singly linked lists" ] }, { "cell_type": "code", "execution_count": null, "id": "a3b1e913-05ca-4d02-8eae-2b45d6df359a", "metadata": {}, "outputs": [], "source": [ "class SinglyLinkedList:\n", "\n", " \n", " class _Node:\n", " \n", " \n", " def __init__(self, element):\n", " self._element = element\n", " self._next = None\n", "\n", " \n", " def __init__(self):\n", " self._head = None\n", " self._tail = None\n", " self._size = 0\n", " \n", " \n", " def add_first(self, element):\n", " new = self._Node(element)\n", " new._next = self._head\n", " self._head = new\n", " if self._size == 0:\n", " self._tail = new\n", " self._size += 1\n", " \n", "\n", " def add_last(self, element):\n", " new = self._Node(element)\n", " new._next = None\n", " if self._size > 0:\n", " self._tail._next = new\n", " else:\n", " self._head = new\n", " self._tail = new\n", " self._size += 1\n", " \n", " \n", " def remove_first(self):\n", " if self._size == 0:\n", " raise Empty('Singly linked list is empty')\n", " self._head = self._head._next\n", " self._size -= 1\n", " \n", " \n", " def is_empty(self):\n", " return self._size == 0\n", " \n", " \n", " def next(self, node=None):\n", " if node:\n", " return node._next\n", " else:\n", " return self._head\n", " \n", " \n", " def __len__(self):\n", " return self._size\n", " \n", " \n", " def __str__(self):\n", " result = '[ '\n", " node = self.next()\n", " while node:\n", " result += str(node._element) + ' '\n", " node = self.next(node)\n", " return result + ']'" ] }, { "cell_type": "code", "execution_count": null, "id": "ffc0c41f-58a0-4b6e-9c19-9aaea823589a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 20 5 10 ]\n", "3\n", "False\n", "[ ]\n", "[ True ]\n" ] } ], "source": [ "list = SinglyLinkedList()\n", "list.add_last(5)\n", "list.add_last(10)\n", "list.add_first(20)\n", "print(list)\n", "print(len(list))\n", "print(list.is_empty())\n", "list.remove_first()\n", "list.remove_first()\n", "list.remove_first()\n", "print(list)\n", "list.add_first(True)\n", "print(list)" ] }, { "cell_type": "code", "execution_count": null, "id": "521a880a-8c07-4ac1-a2c7-4642b36836ff", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": ".venv", "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.13.4" } }, "nbformat": 4, "nbformat_minor": 5 }