\u001b[0m in \u001b[0;36mpush\u001b[0;34m(self, e)\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_maxlen\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_data\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_maxlen\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 31\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mFull\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Stack is full.'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 32\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_data\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
702 | "\u001b[0;31mFull\u001b[0m: Stack is full."
703 | ]
704 | }
705 | ],
706 | "source": [
707 | "sample.push(7)"
708 | ]
709 | },
710 | {
711 | "cell_type": "code",
712 | "execution_count": 27,
713 | "metadata": {},
714 | "outputs": [],
715 | "source": [
716 | "sample_none = ArrayStack()"
717 | ]
718 | },
719 | {
720 | "cell_type": "code",
721 | "execution_count": 28,
722 | "metadata": {},
723 | "outputs": [],
724 | "source": [
725 | "sample_none.push(2)\n",
726 | "sample_none.push(3)\n",
727 | "sample_none.push(4)\n",
728 | "sample_none.push(5)\n",
729 | "sample_none.push(6)"
730 | ]
731 | },
732 | {
733 | "cell_type": "code",
734 | "execution_count": 29,
735 | "metadata": {},
736 | "outputs": [],
737 | "source": [
738 | "sample_none.push(7)"
739 | ]
740 | },
741 | {
742 | "cell_type": "markdown",
743 | "metadata": {},
744 | "source": [
745 | "### C-6.17\n",
746 | "\n",
747 | "In the previous exercise, we assume that the underlying list is initially empty. Redo that exercise, this time preallocating an underlying list with length equal to the stack's maximum capacity."
748 | ]
749 | },
750 | {
751 | "cell_type": "code",
752 | "execution_count": 36,
753 | "metadata": {},
754 | "outputs": [],
755 | "source": [
756 | "# Stack\n",
757 | "\n",
758 | "class Empty(Exception):\n",
759 | " \"\"\"Error attempting to access an element from an empty container.\"\"\"\n",
760 | " pass\n",
761 | "\n",
762 | "class Full(Exception):\n",
763 | " \"\"\"Error when stack is full\"\"\"\n",
764 | " pass\n",
765 | "\n",
766 | "class ArrayStack:\n",
767 | " \"\"\"LIFO Stack implementation using a Python list as underlying storage.\"\"\"\n",
768 | "\n",
769 | " def __init__(self, maxlen=None):\n",
770 | " \"\"\"Create an empty stack.\"\"\"\n",
771 | " self._data = [] if maxlen is None else [None] * maxlen\n",
772 | " self._maxlen = maxlen\n",
773 | "\n",
774 | " def __len__(self):\n",
775 | " \"\"\"Return the number of elements in the stack\"\"\"\n",
776 | " return len(self._data)\n",
777 | "\n",
778 | " @property\n",
779 | " def data(self):\n",
780 | " return self._data\n",
781 | " \n",
782 | " def is_empty(self):\n",
783 | " \"\"\"Return True if the stack is empty.\"\"\"\n",
784 | " return len(self._data) == 0\n",
785 | "\n",
786 | " def push(self, e):\n",
787 | " \"\"\"Add element e to the top of the stack.\"\"\"\n",
788 | " \n",
789 | " if self._maxlen is not None and (len(self._data) >= self._maxlen):\n",
790 | " raise Full('Stack is full.')\n",
791 | " self._data.append(e)\n",
792 | "\n",
793 | " def top(self):\n",
794 | " \"\"\"Return (but do not remove) the element at the top of the stack.\n",
795 | "\n",
796 | " Raise Empty exception if the stack is empty.\n",
797 | " \"\"\"\n",
798 | "\n",
799 | " if self.is_empty():\n",
800 | " raise Empty('Stack is empty')\n",
801 | " return self._data[-1]\n",
802 | "\n",
803 | " def pop(self):\n",
804 | " \"\"\"Remove and return the element from the top of the stack (i.e.,LIFO)\n",
805 | "\n",
806 | " Raise Empty exception if the stack is empty.\n",
807 | " \"\"\"\n",
808 | " if self.is_empty():\n",
809 | " raise Empty('Stack is empty')\n",
810 | " return self._data.pop()"
811 | ]
812 | },
813 | {
814 | "cell_type": "code",
815 | "execution_count": 31,
816 | "metadata": {},
817 | "outputs": [],
818 | "source": [
819 | "x = ArrayStack()"
820 | ]
821 | },
822 | {
823 | "cell_type": "code",
824 | "execution_count": 32,
825 | "metadata": {},
826 | "outputs": [
827 | {
828 | "data": {
829 | "text/plain": [
830 | "[]"
831 | ]
832 | },
833 | "execution_count": 32,
834 | "metadata": {},
835 | "output_type": "execute_result"
836 | }
837 | ],
838 | "source": [
839 | "x._data"
840 | ]
841 | },
842 | {
843 | "cell_type": "code",
844 | "execution_count": 33,
845 | "metadata": {},
846 | "outputs": [
847 | {
848 | "data": {
849 | "text/plain": [
850 | "[None, None, None, None, None, None, None, None, None, None]"
851 | ]
852 | },
853 | "execution_count": 33,
854 | "metadata": {},
855 | "output_type": "execute_result"
856 | }
857 | ],
858 | "source": [
859 | "x = ArrayStack(10)\n",
860 | "x._data"
861 | ]
862 | },
863 | {
864 | "cell_type": "markdown",
865 | "metadata": {},
866 | "source": [
867 | "### C-6.23\n",
868 | "\n",
869 | "Suppose you have three nonempty stacks $R$, $S$, and $T$. Describe a sequence of operations that results in $S$ storing all elements originally in $T$ below all of $S$'s original elements, with both sets of those elements in their original order. The final configuration for $R$ should be the smae as its original configuration. For example, if $R = [1, 2, 3]$, $S=[4,5]$, and $T=[6,7,8,9]$, the final configuration should have $R = [1,2,3]$ and $S=[6,7,8,9,4,5]$."
870 | ]
871 | },
872 | {
873 | "cell_type": "code",
874 | "execution_count": 50,
875 | "metadata": {
876 | "scrolled": false
877 | },
878 | "outputs": [
879 | {
880 | "data": {
881 | "text/plain": [
882 | "[1, 2, 3]"
883 | ]
884 | },
885 | "execution_count": 50,
886 | "metadata": {},
887 | "output_type": "execute_result"
888 | }
889 | ],
890 | "source": [
891 | "r = ArrayStack()\n",
892 | "r.push(1)\n",
893 | "r.push(2)\n",
894 | "r.push(3)\n",
895 | "r.data"
896 | ]
897 | },
898 | {
899 | "cell_type": "code",
900 | "execution_count": 51,
901 | "metadata": {},
902 | "outputs": [
903 | {
904 | "data": {
905 | "text/plain": [
906 | "[4, 5]"
907 | ]
908 | },
909 | "execution_count": 51,
910 | "metadata": {},
911 | "output_type": "execute_result"
912 | }
913 | ],
914 | "source": [
915 | "s = ArrayStack()\n",
916 | "s.push(4)\n",
917 | "s.push(5)\n",
918 | "s.data"
919 | ]
920 | },
921 | {
922 | "cell_type": "code",
923 | "execution_count": 52,
924 | "metadata": {},
925 | "outputs": [
926 | {
927 | "data": {
928 | "text/plain": [
929 | "[6, 7, 8, 9]"
930 | ]
931 | },
932 | "execution_count": 52,
933 | "metadata": {},
934 | "output_type": "execute_result"
935 | }
936 | ],
937 | "source": [
938 | "t = ArrayStack()\n",
939 | "t.push(6)\n",
940 | "t.push(7)\n",
941 | "t.push(8)\n",
942 | "t.push(9)\n",
943 | "t.data"
944 | ]
945 | },
946 | {
947 | "cell_type": "code",
948 | "execution_count": 53,
949 | "metadata": {},
950 | "outputs": [],
951 | "source": [
952 | "r.push(s.pop())\n",
953 | "t.push(s.pop())\n",
954 | "t.push(r.pop())"
955 | ]
956 | },
957 | {
958 | "cell_type": "code",
959 | "execution_count": 54,
960 | "metadata": {},
961 | "outputs": [
962 | {
963 | "data": {
964 | "text/plain": [
965 | "[1, 2, 3]"
966 | ]
967 | },
968 | "execution_count": 54,
969 | "metadata": {},
970 | "output_type": "execute_result"
971 | }
972 | ],
973 | "source": [
974 | "r.data"
975 | ]
976 | },
977 | {
978 | "cell_type": "code",
979 | "execution_count": 55,
980 | "metadata": {},
981 | "outputs": [
982 | {
983 | "data": {
984 | "text/plain": [
985 | "[]"
986 | ]
987 | },
988 | "execution_count": 55,
989 | "metadata": {},
990 | "output_type": "execute_result"
991 | }
992 | ],
993 | "source": [
994 | "s.data"
995 | ]
996 | },
997 | {
998 | "cell_type": "code",
999 | "execution_count": 56,
1000 | "metadata": {},
1001 | "outputs": [
1002 | {
1003 | "data": {
1004 | "text/plain": [
1005 | "[6, 7, 8, 9, 4, 5]"
1006 | ]
1007 | },
1008 | "execution_count": 56,
1009 | "metadata": {},
1010 | "output_type": "execute_result"
1011 | }
1012 | ],
1013 | "source": [
1014 | "t.data"
1015 | ]
1016 | },
1017 | {
1018 | "cell_type": "markdown",
1019 | "metadata": {},
1020 | "source": [
1021 | "### C-6.30\n",
1022 | "\n",
1023 | "Alice has two queues, $Q$ and $R$, which can store integers, Bob gives Alice 50 odd integers and 50 even integers and insists that she store all 100 integers in $Q$ and $R$. They then paly a game where Bob picks $Q$ or $R$ at random and then applies the round-robin scheduler, described in the chapter, to the chosen queue a random number of times. If the last number to be processed at the end of this game was odd, Bob wins. Otherwise Alice wins. How can Alice allocate integers to queues to optimize her change of winnning? What is her chance of winning?"
1024 | ]
1025 | },
1026 | {
1027 | "cell_type": "markdown",
1028 | "metadata": {},
1029 | "source": [
1030 | "#### Answer"
1031 | ]
1032 | },
1033 | {
1034 | "cell_type": "markdown",
1035 | "metadata": {},
1036 | "source": [
1037 | "For me, it is not very intuitive to guess the most probable case that Alice wins, but it is helpful to think two most extreme cases to infer the answer of this question."
1038 | ]
1039 | },
1040 | {
1041 | "cell_type": "markdown",
1042 | "metadata": {},
1043 | "source": [
1044 | "##### Case 1: Distribute almost equally."
1045 | ]
1046 | },
1047 | {
1048 | "cell_type": "markdown",
1049 | "metadata": {},
1050 | "source": [
1051 | "If two queues have equal number of even and odd integers, then probability of Alice can win will be:"
1052 | ]
1053 | },
1054 | {
1055 | "cell_type": "markdown",
1056 | "metadata": {},
1057 | "source": [
1058 | "$$0.5 \\times \\left(\\frac{25}{50} + \\frac{25}{50}\\right) = 50(\\%) $$"
1059 | ]
1060 | },
1061 | {
1062 | "cell_type": "markdown",
1063 | "metadata": {},
1064 | "source": [
1065 | "##### Case 2: Allocate an even number to a queue and others at the other queue."
1066 | ]
1067 | },
1068 | {
1069 | "cell_type": "markdown",
1070 | "metadata": {},
1071 | "source": [
1072 | "This will lead the probablility that Alice wins to:\n",
1073 | "\n",
1074 | "$$0.5 \\times \\left(1 + \\frac{49}{99}\\right) \\approx 74.75(\\%)$$"
1075 | ]
1076 | },
1077 | {
1078 | "cell_type": "markdown",
1079 | "metadata": {},
1080 | "source": [
1081 | "Looks good. Then How about allocating more than one even integers to a queue? Let's test with 25 even integers."
1082 | ]
1083 | },
1084 | {
1085 | "cell_type": "markdown",
1086 | "metadata": {},
1087 | "source": [
1088 | "$$0.5 \\times \\left(1 + \\frac{25}{75}\\right) \\approx 66.67(\\%)$$"
1089 | ]
1090 | },
1091 | {
1092 | "cell_type": "markdown",
1093 | "metadata": {},
1094 | "source": [
1095 | "You might notice that allocating more than one even integer just reduce the Alice's winning probability of the case that Bob chooses the queue which have both even and odd integers. Therefore, Alice should allocate an even integer to one queue."
1096 | ]
1097 | }
1098 | ],
1099 | "metadata": {
1100 | "kernelspec": {
1101 | "display_name": "Python 3",
1102 | "language": "python",
1103 | "name": "python3"
1104 | },
1105 | "language_info": {
1106 | "codemirror_mode": {
1107 | "name": "ipython",
1108 | "version": 3
1109 | },
1110 | "file_extension": ".py",
1111 | "mimetype": "text/x-python",
1112 | "name": "python",
1113 | "nbconvert_exporter": "python",
1114 | "pygments_lexer": "ipython3",
1115 | "version": "3.7.3"
1116 | }
1117 | },
1118 | "nbformat": 4,
1119 | "nbformat_minor": 1
1120 | }
1121 |
--------------------------------------------------------------------------------
/Exercises/Chapter_07.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Chapter 07"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "import copy"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "## Exercises"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {},
29 | "source": [
30 | "### R-7.2\n",
31 | "\n",
32 | "Describe a good algorithm for concatenating two singly linked lists L and M, given only reference to the first node of each list, into a single list $L^\\prime$ that contains all the nodes of $L$ followed by all nodes of $M$."
33 | ]
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "metadata": {},
38 | "source": [
39 | "##### Answer"
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "execution_count": 2,
45 | "metadata": {},
46 | "outputs": [],
47 | "source": [
48 | "class Empty(Exception):\n",
49 | " pass"
50 | ]
51 | },
52 | {
53 | "cell_type": "code",
54 | "execution_count": 3,
55 | "metadata": {},
56 | "outputs": [],
57 | "source": [
58 | "class LinkedStack:\n",
59 | " \"\"\"LIFO Stack implementatino using a singly linked list for storage\"\"\"\n",
60 | " \n",
61 | " class _Node:\n",
62 | " __slots__ = '_element', '_next'\n",
63 | " \n",
64 | " def __init__(self, element, nxt):\n",
65 | " self._element = element\n",
66 | " self._next = nxt\n",
67 | " \n",
68 | " \n",
69 | " def __init__(self):\n",
70 | " self._head = None\n",
71 | " self._size = 0\n",
72 | " \n",
73 | " def __len__(self):\n",
74 | " return self._size\n",
75 | " \n",
76 | " def __iter__(self):\n",
77 | " cur = self._head\n",
78 | " while cur is not None:\n",
79 | " yield cur._element\n",
80 | " cur = cur._next\n",
81 | " \n",
82 | " def is_empty(self):\n",
83 | " return self._size == 0\n",
84 | " \n",
85 | " def push(self, e):\n",
86 | " self._head = self._Node(e, self._head)\n",
87 | " self._size += 1\n",
88 | " \n",
89 | " def top(self):\n",
90 | " if self.is_empty():\n",
91 | " raise Empty('Stack is empty')\n",
92 | " return self._head._element\n",
93 | " \n",
94 | " def pop(self):\n",
95 | " if self.is_empty():\n",
96 | " raise Empty('Stack is empty')\n",
97 | " answer = self._head._element\n",
98 | " self._head = self._head._next\n",
99 | " self._size -= 1\n",
100 | " return answer\n"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": 4,
106 | "metadata": {},
107 | "outputs": [],
108 | "source": [
109 | "L = LinkedStack()"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": 5,
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "L.push(5)\n",
119 | "L.push(4)\n",
120 | "L.push(3)"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 6,
126 | "metadata": {},
127 | "outputs": [
128 | {
129 | "data": {
130 | "text/plain": [
131 | "[3, 4, 5]"
132 | ]
133 | },
134 | "execution_count": 6,
135 | "metadata": {},
136 | "output_type": "execute_result"
137 | }
138 | ],
139 | "source": [
140 | "[i for i in L]"
141 | ]
142 | },
143 | {
144 | "cell_type": "code",
145 | "execution_count": 7,
146 | "metadata": {},
147 | "outputs": [],
148 | "source": [
149 | "M = LinkedStack()\n",
150 | "M.push(3)\n",
151 | "M.push(2)\n",
152 | "M.push(1)"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": 8,
158 | "metadata": {},
159 | "outputs": [
160 | {
161 | "data": {
162 | "text/plain": [
163 | "[1, 2, 3]"
164 | ]
165 | },
166 | "execution_count": 8,
167 | "metadata": {},
168 | "output_type": "execute_result"
169 | }
170 | ],
171 | "source": [
172 | "[i for i in M]"
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "metadata": {},
178 | "source": [
179 | "Making a new `LinkedStack` is less efficient ($n$ pop & $n$ push for each list) than just making the base list's last node to designate the head of the list to be appended ($n$ references for traversing). "
180 | ]
181 | },
182 | {
183 | "cell_type": "code",
184 | "execution_count": 9,
185 | "metadata": {},
186 | "outputs": [],
187 | "source": [
188 | "def concat_singly_linked_stack(base, append):\n",
189 | " \n",
190 | " base = copy.deepcopy(base)\n",
191 | " append = copy.deepcopy(append)\n",
192 | " \n",
193 | " base_last = None\n",
194 | " cur = base._head\n",
195 | " while True: # Need to traverse whole list since LinkedStack does not keep its last node.\n",
196 | " if cur._next is None:\n",
197 | " base_last = cur\n",
198 | " break\n",
199 | " cur = cur._next\n",
200 | " base_last._next = append._head\n",
201 | " base._size += append._size\n",
202 | " return base"
203 | ]
204 | },
205 | {
206 | "cell_type": "code",
207 | "execution_count": 10,
208 | "metadata": {},
209 | "outputs": [],
210 | "source": [
211 | "concat_list = concat_singly_linked_stack(L, M)"
212 | ]
213 | },
214 | {
215 | "cell_type": "code",
216 | "execution_count": 11,
217 | "metadata": {},
218 | "outputs": [
219 | {
220 | "data": {
221 | "text/plain": [
222 | "[3, 4, 5, 1, 2, 3]"
223 | ]
224 | },
225 | "execution_count": 11,
226 | "metadata": {},
227 | "output_type": "execute_result"
228 | }
229 | ],
230 | "source": [
231 | "[i for i in concat_list]"
232 | ]
233 | },
234 | {
235 | "cell_type": "markdown",
236 | "metadata": {},
237 | "source": [
238 | "### R-7.3\n",
239 | "\n",
240 | "Describe a recursive algorithm that counts the number of nodes in a singly linked list."
241 | ]
242 | },
243 | {
244 | "cell_type": "markdown",
245 | "metadata": {},
246 | "source": [
247 | "##### Answer"
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "execution_count": 12,
253 | "metadata": {},
254 | "outputs": [],
255 | "source": [
256 | "def recursive_count(list_head):\n",
257 | " \"\"\"\n",
258 | " list_head: head reference to a list\n",
259 | " \"\"\"\n",
260 | " \n",
261 | " if list_head._next is None:\n",
262 | " return 1\n",
263 | " else:\n",
264 | " return 1 + recursive_count(list_head._next)\n"
265 | ]
266 | },
267 | {
268 | "cell_type": "code",
269 | "execution_count": 13,
270 | "metadata": {},
271 | "outputs": [
272 | {
273 | "data": {
274 | "text/plain": [
275 | "6"
276 | ]
277 | },
278 | "execution_count": 13,
279 | "metadata": {},
280 | "output_type": "execute_result"
281 | }
282 | ],
283 | "source": [
284 | "recursive_count(concat_list._head)"
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "metadata": {},
290 | "source": [
291 | "### R-7.7\n",
292 | "\n",
293 | "Our `CircularQueue` class provides a `rotate()` method that has semantics equivalent to `Q.enqueue(Q.dequeue())`, for a nonempty queue. Implement such a method for the `LinkedQueue ` class without the creation of any new nodes."
294 | ]
295 | },
296 | {
297 | "cell_type": "markdown",
298 | "metadata": {},
299 | "source": [
300 | "##### Answer"
301 | ]
302 | },
303 | {
304 | "cell_type": "code",
305 | "execution_count": 14,
306 | "metadata": {},
307 | "outputs": [],
308 | "source": [
309 | "class LinkedQueue:\n",
310 | " \n",
311 | " class _Node:\n",
312 | " __slots__ = '_element', '_next'\n",
313 | " \n",
314 | " def __init__(self, element, nxt):\n",
315 | " self._element = element\n",
316 | " self._next = nxt\n",
317 | " \n",
318 | " def __init__(self):\n",
319 | " self._head = None\n",
320 | " self._tail = None\n",
321 | " self._size = 0\n",
322 | " \n",
323 | " def __len__(self):\n",
324 | " return self._size\n",
325 | " \n",
326 | " def __iter__(self):\n",
327 | " cur = self._head\n",
328 | " while cur is not None:\n",
329 | " yield cur._element\n",
330 | " cur = cur._next\n",
331 | " \n",
332 | " def is_empty(self):\n",
333 | " return self._size == 0\n",
334 | " \n",
335 | " def first(self):\n",
336 | " if self.is_empty():\n",
337 | " raise Empty(\"Queue is empty\")\n",
338 | " return self._head._element\n",
339 | " \n",
340 | " def dequeue(self):\n",
341 | " \n",
342 | " if self.is_empty():\n",
343 | " raise Empty(\"Queue is empty\")\n",
344 | " answer = self._head._element\n",
345 | " self._head = self._head._next\n",
346 | " self._size -= 1\n",
347 | " if self.is_empty():\n",
348 | " self._tail = None\n",
349 | " return answer\n",
350 | " \n",
351 | " def enqueue(self, e):\n",
352 | " \n",
353 | " newest = self._Node(e, None)\n",
354 | " if self.is_empty():\n",
355 | " self._head = newest\n",
356 | " else:\n",
357 | " self._tail._next = newest\n",
358 | " self._tail = newest\n",
359 | " self._size += 1\n",
360 | " "
361 | ]
362 | },
363 | {
364 | "cell_type": "markdown",
365 | "metadata": {},
366 | "source": [
367 | "`rotate` method in `LinkedQueue` should `dequeue` the first element and insert it back into its tail by `enqueue`"
368 | ]
369 | },
370 | {
371 | "cell_type": "code",
372 | "execution_count": 15,
373 | "metadata": {},
374 | "outputs": [],
375 | "source": [
376 | "def rotate(self):\n",
377 | " if self._size > 0:\n",
378 | " old_head = self._head\n",
379 | " self._head = old_head._next\n",
380 | " self._tail._next = old_head\n",
381 | " old_head._next = None\n",
382 | " \n",
383 | "LinkedQueue.rotate = rotate # monkey patching"
384 | ]
385 | },
386 | {
387 | "cell_type": "code",
388 | "execution_count": 16,
389 | "metadata": {},
390 | "outputs": [],
391 | "source": [
392 | "q = LinkedQueue()\n",
393 | "q.enqueue(5)\n",
394 | "q.enqueue(4)\n",
395 | "q.enqueue(3)\n",
396 | "q.enqueue(2)\n",
397 | "q.enqueue(1)"
398 | ]
399 | },
400 | {
401 | "cell_type": "code",
402 | "execution_count": 17,
403 | "metadata": {},
404 | "outputs": [],
405 | "source": [
406 | "q.rotate()"
407 | ]
408 | },
409 | {
410 | "cell_type": "code",
411 | "execution_count": 18,
412 | "metadata": {},
413 | "outputs": [
414 | {
415 | "data": {
416 | "text/plain": [
417 | "[4, 3, 2, 1, 5]"
418 | ]
419 | },
420 | "execution_count": 18,
421 | "metadata": {},
422 | "output_type": "execute_result"
423 | }
424 | ],
425 | "source": [
426 | "[i for i in q]"
427 | ]
428 | },
429 | {
430 | "cell_type": "markdown",
431 | "metadata": {},
432 | "source": [
433 | "### R-7.13"
434 | ]
435 | },
436 | {
437 | "cell_type": "markdown",
438 | "metadata": {},
439 | "source": [
440 | "Update the `PositionalList` class to support an additional method `find(e)`, which returns the position of the (first occurrence of )element `e` in the list (or None if not found)."
441 | ]
442 | },
443 | {
444 | "cell_type": "code",
445 | "execution_count": 19,
446 | "metadata": {},
447 | "outputs": [],
448 | "source": [
449 | "class _DoublyLinkedBase:\n",
450 | " \"\"\"A base calss providing a doubly linked list representation.\"\"\"\n",
451 | " \n",
452 | " class _Node:\n",
453 | " __slots__ = '_element', '_prev', '_next'\n",
454 | " \n",
455 | " def __init__(self, element, prev, nxt):\n",
456 | " self._element = element\n",
457 | " self._prev = prev\n",
458 | " self._next = nxt\n",
459 | " \n",
460 | " def __init__(self):\n",
461 | " self._header = self._Node(None, None, None)\n",
462 | " self._trailer = self._Node(None, None, None)\n",
463 | " self._header._next = self._trailer\n",
464 | " self._trailer._prev = self._header\n",
465 | " self._size = 0\n",
466 | " \n",
467 | " def __len__(self):\n",
468 | " return self._size\n",
469 | " \n",
470 | " def is_empty(self):\n",
471 | " return self._size == 0\n",
472 | " \n",
473 | " def _insert_between(self, e, predecessor, successor):\n",
474 | " newest = self._Node(e, predecessor, successor)\n",
475 | " predecessor._next = newest\n",
476 | " successor._prev = newest\n",
477 | " self._size += 1\n",
478 | " return newest\n",
479 | " \n",
480 | " def _delete_node(self, node):\n",
481 | " predecessor = node._prev\n",
482 | " successor = node._next\n",
483 | " predecessor._next = successor\n",
484 | " successor._prev = predecessor\n",
485 | " self._size -= 1\n",
486 | " element = node._element\n",
487 | " node._prev = node._next = node._element = None\n",
488 | " return element"
489 | ]
490 | },
491 | {
492 | "cell_type": "code",
493 | "execution_count": 20,
494 | "metadata": {},
495 | "outputs": [],
496 | "source": [
497 | "class PositionalList(_DoublyLinkedBase):\n",
498 | " \n",
499 | " class Position:\n",
500 | " \"\"\"An abstraction representing the location of a single element.\"\"\"\n",
501 | " \n",
502 | " def __init__(self, container, node):\n",
503 | " self._container = container\n",
504 | " self._node = node\n",
505 | " \n",
506 | " def element(self):\n",
507 | " return self._node._element\n",
508 | " \n",
509 | " def __eq__(self, other):\n",
510 | " return type(other) is type(self) and other._Node is self._node\n",
511 | " \n",
512 | " def __ne__(self, other):\n",
513 | " return not (self == other)\n",
514 | " \n",
515 | " \n",
516 | " def _validate(self, p):\n",
517 | " if not isinstance(p, self.Position):\n",
518 | " raise TypeError('p must be proper Position type')\n",
519 | " if p._container is not self:\n",
520 | " raise ValueError('p does not belong to this container')\n",
521 | " if p._node._next is None:\n",
522 | " raise ValueError('p is no longer valid')\n",
523 | " return p._node\n",
524 | " \n",
525 | " \n",
526 | " def _make_position(self, node):\n",
527 | " if node is self._header or node is self._trailer:\n",
528 | " return None\n",
529 | " else:\n",
530 | " return self.Position(self, node)\n",
531 | " \n",
532 | " def first(self):\n",
533 | " return self._make_position(self._header._next)\n",
534 | " \n",
535 | " def last(self):\n",
536 | " return self._make_position(self._trailer._prev)\n",
537 | " \n",
538 | " def before(self, p):\n",
539 | " node = self._validate(p)\n",
540 | " return self._make_position(node._prev)\n",
541 | " \n",
542 | " def after(self, p):\n",
543 | " node = self._validate(p)\n",
544 | " return self._make_position(node._next)\n",
545 | " \n",
546 | " def __iter__(self):\n",
547 | " cursor = self.first()\n",
548 | " while cursor is not None:\n",
549 | " yield cursor.element()\n",
550 | " cursor = self.after(cursor)\n",
551 | " \n",
552 | " def _insert_between(self, e, predecessor, successor):\n",
553 | " node = super()._insert_between(e, predecessor, successor)\n",
554 | " return self._make_position(node)\n",
555 | " \n",
556 | " def add_first(self, e):\n",
557 | " return self._insert_between(e, self._header, self._header._next)\n",
558 | " \n",
559 | " def add_last(self, e):\n",
560 | " return self._insert_between(e, self._trailer._prev, self._trailer)\n",
561 | " \n",
562 | " def add_before(self, p, e):\n",
563 | " original = self._validate(p)\n",
564 | " return self._insert_between(e, original._prev, original)\n",
565 | " \n",
566 | " def add_after(self, p, e):\n",
567 | " original = self._validate(p)\n",
568 | " return self._insert_between(e, original, original._next)\n",
569 | " \n",
570 | " def delete(self, p):\n",
571 | " original = self._validate(p)\n",
572 | " return self._delete_node(original)\n",
573 | " \n",
574 | " def replace(self, p, e):\n",
575 | " original = self._validate(p)\n",
576 | " old_value = original._element\n",
577 | " original._element = e\n",
578 | " return old_value\n",
579 | " "
580 | ]
581 | },
582 | {
583 | "cell_type": "code",
584 | "execution_count": 21,
585 | "metadata": {},
586 | "outputs": [],
587 | "source": [
588 | "def find(self, e):\n",
589 | " cur = self.first()\n",
590 | " while True:\n",
591 | " if cur is None:\n",
592 | " return None\n",
593 | " if cur.element() == e:\n",
594 | " return cur\n",
595 | " cur = self.after(cur)\n",
596 | "\n",
597 | "PositionalList.find = find # Monkey patching"
598 | ]
599 | },
600 | {
601 | "cell_type": "code",
602 | "execution_count": 22,
603 | "metadata": {},
604 | "outputs": [],
605 | "source": [
606 | "p = PositionalList()"
607 | ]
608 | },
609 | {
610 | "cell_type": "code",
611 | "execution_count": 23,
612 | "metadata": {},
613 | "outputs": [],
614 | "source": [
615 | "for i in [2, 8 ,1, 10, 9, 8, 4, 3]:\n",
616 | " p.add_first(i)"
617 | ]
618 | },
619 | {
620 | "cell_type": "code",
621 | "execution_count": 24,
622 | "metadata": {},
623 | "outputs": [
624 | {
625 | "data": {
626 | "text/plain": [
627 | "3"
628 | ]
629 | },
630 | "execution_count": 24,
631 | "metadata": {},
632 | "output_type": "execute_result"
633 | }
634 | ],
635 | "source": [
636 | "p.first().element()"
637 | ]
638 | },
639 | {
640 | "cell_type": "code",
641 | "execution_count": 25,
642 | "metadata": {},
643 | "outputs": [
644 | {
645 | "data": {
646 | "text/plain": [
647 | "[3, 4, 8, 9, 10, 1, 8, 2]"
648 | ]
649 | },
650 | "execution_count": 25,
651 | "metadata": {},
652 | "output_type": "execute_result"
653 | }
654 | ],
655 | "source": [
656 | "[i for i in p]"
657 | ]
658 | },
659 | {
660 | "cell_type": "code",
661 | "execution_count": 26,
662 | "metadata": {},
663 | "outputs": [
664 | {
665 | "data": {
666 | "text/plain": [
667 | "<__main__.PositionalList.Position at 0x7fc2a05e9be0>"
668 | ]
669 | },
670 | "execution_count": 26,
671 | "metadata": {},
672 | "output_type": "execute_result"
673 | }
674 | ],
675 | "source": [
676 | "p.find(10)"
677 | ]
678 | },
679 | {
680 | "cell_type": "code",
681 | "execution_count": 27,
682 | "metadata": {},
683 | "outputs": [
684 | {
685 | "data": {
686 | "text/plain": [
687 | "9"
688 | ]
689 | },
690 | "execution_count": 27,
691 | "metadata": {},
692 | "output_type": "execute_result"
693 | }
694 | ],
695 | "source": [
696 | "p.before(p.find(10)).element()"
697 | ]
698 | },
699 | {
700 | "cell_type": "code",
701 | "execution_count": 28,
702 | "metadata": {},
703 | "outputs": [
704 | {
705 | "data": {
706 | "text/plain": [
707 | "<__main__.PositionalList.Position at 0x7fc2a063aba8>"
708 | ]
709 | },
710 | "execution_count": 28,
711 | "metadata": {},
712 | "output_type": "execute_result"
713 | }
714 | ],
715 | "source": [
716 | "p.find(8)"
717 | ]
718 | },
719 | {
720 | "cell_type": "code",
721 | "execution_count": 29,
722 | "metadata": {},
723 | "outputs": [
724 | {
725 | "data": {
726 | "text/plain": [
727 | "9"
728 | ]
729 | },
730 | "execution_count": 29,
731 | "metadata": {},
732 | "output_type": "execute_result"
733 | }
734 | ],
735 | "source": [
736 | "p.after(p.find(8)).element()"
737 | ]
738 | },
739 | {
740 | "cell_type": "code",
741 | "execution_count": 30,
742 | "metadata": {},
743 | "outputs": [],
744 | "source": [
745 | "p.find(99) # Not found: None"
746 | ]
747 | },
748 | {
749 | "cell_type": "markdown",
750 | "metadata": {},
751 | "source": [
752 | "### R-7.14\n",
753 | "\n",
754 | "Repeat the previous process using recursion. Your method should not contain any loops. How much space does your method use in addition to the space used for $L$?"
755 | ]
756 | },
757 | {
758 | "cell_type": "code",
759 | "execution_count": 31,
760 | "metadata": {},
761 | "outputs": [],
762 | "source": [
763 | "def find_recursive(self, cur_pos, e):\n",
764 | " \n",
765 | " if cur_pos is None:\n",
766 | " return None\n",
767 | " elif cur_pos.element() == e:\n",
768 | " return cur_pos\n",
769 | " else:\n",
770 | " cur_pos = self.after(cur_pos)\n",
771 | " return find_recursive(self, cur_pos, e)\n",
772 | " \n",
773 | "\n",
774 | "PositionalList.find_recursive = find_recursive # Monkey patching"
775 | ]
776 | },
777 | {
778 | "cell_type": "code",
779 | "execution_count": 32,
780 | "metadata": {},
781 | "outputs": [
782 | {
783 | "data": {
784 | "text/plain": [
785 | "[3, 4, 8, 9, 10, 1, 8, 2]"
786 | ]
787 | },
788 | "execution_count": 32,
789 | "metadata": {},
790 | "output_type": "execute_result"
791 | }
792 | ],
793 | "source": [
794 | "[i for i in p]"
795 | ]
796 | },
797 | {
798 | "cell_type": "code",
799 | "execution_count": 33,
800 | "metadata": {},
801 | "outputs": [
802 | {
803 | "data": {
804 | "text/plain": [
805 | "<__main__.PositionalList.Position at 0x7fc2a05e9a20>"
806 | ]
807 | },
808 | "execution_count": 33,
809 | "metadata": {},
810 | "output_type": "execute_result"
811 | }
812 | ],
813 | "source": [
814 | "p.find_recursive(p.first(), 1)"
815 | ]
816 | },
817 | {
818 | "cell_type": "code",
819 | "execution_count": 34,
820 | "metadata": {},
821 | "outputs": [
822 | {
823 | "data": {
824 | "text/plain": [
825 | "10"
826 | ]
827 | },
828 | "execution_count": 34,
829 | "metadata": {},
830 | "output_type": "execute_result"
831 | }
832 | ],
833 | "source": [
834 | "p.before(p.find_recursive(p.first(), 1)).element()"
835 | ]
836 | },
837 | {
838 | "cell_type": "code",
839 | "execution_count": 35,
840 | "metadata": {},
841 | "outputs": [
842 | {
843 | "data": {
844 | "text/plain": [
845 | "<__main__.PositionalList.Position at 0x7fc2a0650588>"
846 | ]
847 | },
848 | "execution_count": 35,
849 | "metadata": {},
850 | "output_type": "execute_result"
851 | }
852 | ],
853 | "source": [
854 | "p.find_recursive(p.first(), 8)"
855 | ]
856 | },
857 | {
858 | "cell_type": "code",
859 | "execution_count": 36,
860 | "metadata": {},
861 | "outputs": [
862 | {
863 | "data": {
864 | "text/plain": [
865 | "9"
866 | ]
867 | },
868 | "execution_count": 36,
869 | "metadata": {},
870 | "output_type": "execute_result"
871 | }
872 | ],
873 | "source": [
874 | "p.after(p.find_recursive(p.first(), 8)).element()"
875 | ]
876 | },
877 | {
878 | "cell_type": "code",
879 | "execution_count": 37,
880 | "metadata": {},
881 | "outputs": [],
882 | "source": [
883 | "p.find_recursive(p.first(), 99) # Not found: None"
884 | ]
885 | },
886 | {
887 | "cell_type": "markdown",
888 | "metadata": {},
889 | "source": [
890 | "### C-7.24\n",
891 | "\n",
892 | "Give a complete implementation of the stack ADT using a singly linked list that *includes a header sentinel*."
893 | ]
894 | },
895 | {
896 | "cell_type": "code",
897 | "execution_count": 38,
898 | "metadata": {},
899 | "outputs": [],
900 | "source": [
901 | "class LinkedStackwithSentinel:\n",
902 | " \"\"\"LIFO Stack implementatino using a singly linked list for storage\"\"\"\n",
903 | " \n",
904 | " class _Node:\n",
905 | " __slots__ = '_element', '_next'\n",
906 | " \n",
907 | " def __init__(self, element, nxt):\n",
908 | " self._element = element\n",
909 | " self._next = nxt\n",
910 | " \n",
911 | " \n",
912 | " def __init__(self):\n",
913 | " self._header = self._Node(None, None)\n",
914 | " self._header._next = None\n",
915 | " self._size = 0\n",
916 | " \n",
917 | " def __len__(self):\n",
918 | " return self._size\n",
919 | " \n",
920 | " def is_empty(self):\n",
921 | " return self._size == 0\n",
922 | " \n",
923 | " def push(self, e):\n",
924 | " new = self._Node(e, self._header._next)\n",
925 | " self._header._next = new\n",
926 | " self._size += 1\n",
927 | " \n",
928 | " def top(self):\n",
929 | " if self.is_empty():\n",
930 | " raise Empty('Stack is empty')\n",
931 | " return self._header._next._element\n",
932 | " \n",
933 | " def pop(self):\n",
934 | " if self.is_empty():\n",
935 | " raise Empty('Stack is empty')\n",
936 | " pop_node = self._header._next\n",
937 | " self._header._next = pop_node._next\n",
938 | " answer = pop_node._element\n",
939 | " pop_node = None\n",
940 | " self._size -= 1\n",
941 | " return answer"
942 | ]
943 | },
944 | {
945 | "cell_type": "code",
946 | "execution_count": 39,
947 | "metadata": {},
948 | "outputs": [],
949 | "source": [
950 | "x = LinkedStackwithSentinel()"
951 | ]
952 | },
953 | {
954 | "cell_type": "code",
955 | "execution_count": 40,
956 | "metadata": {},
957 | "outputs": [],
958 | "source": [
959 | "x.push(5)\n",
960 | "x.push(3)\n",
961 | "x.push(1)"
962 | ]
963 | },
964 | {
965 | "cell_type": "code",
966 | "execution_count": 41,
967 | "metadata": {},
968 | "outputs": [
969 | {
970 | "data": {
971 | "text/plain": [
972 | "1"
973 | ]
974 | },
975 | "execution_count": 41,
976 | "metadata": {},
977 | "output_type": "execute_result"
978 | }
979 | ],
980 | "source": [
981 | "x.top()"
982 | ]
983 | },
984 | {
985 | "cell_type": "code",
986 | "execution_count": 42,
987 | "metadata": {},
988 | "outputs": [
989 | {
990 | "name": "stdout",
991 | "output_type": "stream",
992 | "text": [
993 | "1\n",
994 | "3\n",
995 | "5\n"
996 | ]
997 | }
998 | ],
999 | "source": [
1000 | "print(x.pop())\n",
1001 | "print(x.pop())\n",
1002 | "print(x.pop())"
1003 | ]
1004 | },
1005 | {
1006 | "cell_type": "code",
1007 | "execution_count": 43,
1008 | "metadata": {},
1009 | "outputs": [
1010 | {
1011 | "name": "stdout",
1012 | "output_type": "stream",
1013 | "text": [
1014 | "proper error\n"
1015 | ]
1016 | }
1017 | ],
1018 | "source": [
1019 | "try:\n",
1020 | " x.pop()\n",
1021 | " \n",
1022 | "except Empty:\n",
1023 | " print(\"proper error\")"
1024 | ]
1025 | },
1026 | {
1027 | "cell_type": "markdown",
1028 | "metadata": {},
1029 | "source": [
1030 | "### C-7.25\n",
1031 | "\n",
1032 | "Give a complete implementation of the queue ADT using a singly linked list that includes a header sentinel."
1033 | ]
1034 | },
1035 | {
1036 | "cell_type": "code",
1037 | "execution_count": 44,
1038 | "metadata": {},
1039 | "outputs": [],
1040 | "source": [
1041 | "class LinkedQueuewithSentinel:\n",
1042 | " \n",
1043 | " class _Node:\n",
1044 | " __slots__ = '_element', '_next'\n",
1045 | " \n",
1046 | " def __init__(self, element, nxt):\n",
1047 | " self._element = element\n",
1048 | " self._next = nxt\n",
1049 | " \n",
1050 | " def __init__(self):\n",
1051 | " self._header = self._Node(None, None)\n",
1052 | " self._header._next = None\n",
1053 | " self._tail = None\n",
1054 | " self._size = 0\n",
1055 | " \n",
1056 | " def __len__(self):\n",
1057 | " return self._size\n",
1058 | " \n",
1059 | " def is_empty(self):\n",
1060 | " return self._size == 0\n",
1061 | " \n",
1062 | " def first(self):\n",
1063 | " if self.is_empty():\n",
1064 | " raise Empty(\"Queue is empty\")\n",
1065 | " return self._header._next._element\n",
1066 | " \n",
1067 | " def dequeue(self):\n",
1068 | " \n",
1069 | " if self.is_empty():\n",
1070 | " raise Empty(\"Queue is empty\")\n",
1071 | " dequeue_node = self._header._next\n",
1072 | " self._header._next = dequeue_node._next\n",
1073 | " answer = dequeue_node._element\n",
1074 | " dequeue_node = None\n",
1075 | " self._size -= 1\n",
1076 | " if self.is_empty():\n",
1077 | " self._tail = None\n",
1078 | " return answer\n",
1079 | " \n",
1080 | " def enqueue(self, e):\n",
1081 | " \n",
1082 | " newest = self._Node(e, None)\n",
1083 | " if self.is_empty():\n",
1084 | " self._header._next = newest\n",
1085 | " else:\n",
1086 | " self._tail._next = newest\n",
1087 | " self._tail = newest\n",
1088 | " self._size += 1\n",
1089 | " "
1090 | ]
1091 | },
1092 | {
1093 | "cell_type": "code",
1094 | "execution_count": 45,
1095 | "metadata": {},
1096 | "outputs": [],
1097 | "source": [
1098 | "x = LinkedQueuewithSentinel()"
1099 | ]
1100 | },
1101 | {
1102 | "cell_type": "code",
1103 | "execution_count": 46,
1104 | "metadata": {},
1105 | "outputs": [],
1106 | "source": [
1107 | "x.enqueue(5)\n",
1108 | "x.enqueue(4)\n",
1109 | "x.enqueue(3)"
1110 | ]
1111 | },
1112 | {
1113 | "cell_type": "code",
1114 | "execution_count": 47,
1115 | "metadata": {},
1116 | "outputs": [
1117 | {
1118 | "data": {
1119 | "text/plain": [
1120 | "5"
1121 | ]
1122 | },
1123 | "execution_count": 47,
1124 | "metadata": {},
1125 | "output_type": "execute_result"
1126 | }
1127 | ],
1128 | "source": [
1129 | "x.first()"
1130 | ]
1131 | },
1132 | {
1133 | "cell_type": "code",
1134 | "execution_count": 48,
1135 | "metadata": {},
1136 | "outputs": [
1137 | {
1138 | "data": {
1139 | "text/plain": [
1140 | "5"
1141 | ]
1142 | },
1143 | "execution_count": 48,
1144 | "metadata": {},
1145 | "output_type": "execute_result"
1146 | }
1147 | ],
1148 | "source": [
1149 | "x.dequeue()"
1150 | ]
1151 | },
1152 | {
1153 | "cell_type": "code",
1154 | "execution_count": 49,
1155 | "metadata": {},
1156 | "outputs": [
1157 | {
1158 | "data": {
1159 | "text/plain": [
1160 | "4"
1161 | ]
1162 | },
1163 | "execution_count": 49,
1164 | "metadata": {},
1165 | "output_type": "execute_result"
1166 | }
1167 | ],
1168 | "source": [
1169 | "x.dequeue()"
1170 | ]
1171 | },
1172 | {
1173 | "cell_type": "code",
1174 | "execution_count": 50,
1175 | "metadata": {},
1176 | "outputs": [],
1177 | "source": [
1178 | "x.enqueue(10)"
1179 | ]
1180 | },
1181 | {
1182 | "cell_type": "code",
1183 | "execution_count": 51,
1184 | "metadata": {},
1185 | "outputs": [
1186 | {
1187 | "data": {
1188 | "text/plain": [
1189 | "3"
1190 | ]
1191 | },
1192 | "execution_count": 51,
1193 | "metadata": {},
1194 | "output_type": "execute_result"
1195 | }
1196 | ],
1197 | "source": [
1198 | "x.dequeue()"
1199 | ]
1200 | },
1201 | {
1202 | "cell_type": "code",
1203 | "execution_count": 52,
1204 | "metadata": {},
1205 | "outputs": [
1206 | {
1207 | "data": {
1208 | "text/plain": [
1209 | "10"
1210 | ]
1211 | },
1212 | "execution_count": 52,
1213 | "metadata": {},
1214 | "output_type": "execute_result"
1215 | }
1216 | ],
1217 | "source": [
1218 | "x.first()"
1219 | ]
1220 | },
1221 | {
1222 | "cell_type": "code",
1223 | "execution_count": 53,
1224 | "metadata": {},
1225 | "outputs": [
1226 | {
1227 | "data": {
1228 | "text/plain": [
1229 | "10"
1230 | ]
1231 | },
1232 | "execution_count": 53,
1233 | "metadata": {},
1234 | "output_type": "execute_result"
1235 | }
1236 | ],
1237 | "source": [
1238 | "x.dequeue()"
1239 | ]
1240 | },
1241 | {
1242 | "cell_type": "code",
1243 | "execution_count": 54,
1244 | "metadata": {},
1245 | "outputs": [
1246 | {
1247 | "name": "stdout",
1248 | "output_type": "stream",
1249 | "text": [
1250 | "proper error\n"
1251 | ]
1252 | }
1253 | ],
1254 | "source": [
1255 | "try:\n",
1256 | " x.dequeue()\n",
1257 | "except Empty:\n",
1258 | " print(\"proper error\")"
1259 | ]
1260 | }
1261 | ],
1262 | "metadata": {
1263 | "kernelspec": {
1264 | "display_name": "Python 3",
1265 | "language": "python",
1266 | "name": "python3"
1267 | },
1268 | "language_info": {
1269 | "codemirror_mode": {
1270 | "name": "ipython",
1271 | "version": 3
1272 | },
1273 | "file_extension": ".py",
1274 | "mimetype": "text/x-python",
1275 | "name": "python",
1276 | "nbconvert_exporter": "python",
1277 | "pygments_lexer": "ipython3",
1278 | "version": "3.8.3"
1279 | }
1280 | },
1281 | "nbformat": 4,
1282 | "nbformat_minor": 4
1283 | }
1284 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 
4 |
5 |
6 |
7 | Brief, very brief summary of ***the Data Structures and Algorithms in Python*** book and worked solutions.
8 |
9 | 
10 |
11 | ## Environment / Installation
12 |
13 | * Python 3.8
14 |
15 | Intall dependencies for this repo.
16 |
17 | ```bash
18 | $ pip install -r requirements.txt
19 | ```
20 |
21 | ## Contents
22 |
23 | |Chapter|Contents|Exercise|
24 | |---|---|---|
25 | |Chapter 01| N/A |[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_01.ipynb)|
26 | |Chapter 02|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_02.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_02.ipynb)|
27 | |Chapter 03|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_03.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_03.ipynb)|
28 | |Chapter 04|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_04.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_04.ipynb)|
29 | |Chapter 05|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_05.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_05.ipynb)|
30 | |Chapter 06|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_06.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_06.ipynb)|
31 | |Chapter 07|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_07.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_07.ipynb)|
32 | |Chapter 08|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_08.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_08.ipynb)|
33 | |Chapter 09|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Contents/Chapter_09.ipynb)|[Notebook](https://github.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/blob/main/Exercises/Chapter_09.ipynb)|
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/88920c1cbdb655c5bfe18ad3e74624d6745ab625/assets/logo.png
--------------------------------------------------------------------------------
/images/Fig2.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/88920c1cbdb655c5bfe18ad3e74624d6745ab625/images/Fig2.7.png
--------------------------------------------------------------------------------
/images/Fig7.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/88920c1cbdb655c5bfe18ad3e74624d6745ab625/images/Fig7.1.png
--------------------------------------------------------------------------------
/images/Fig7.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/88920c1cbdb655c5bfe18ad3e74624d6745ab625/images/Fig7.8.png
--------------------------------------------------------------------------------
/images/Fig7.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/88920c1cbdb655c5bfe18ad3e74624d6745ab625/images/Fig7.9.png
--------------------------------------------------------------------------------
/images/improper_tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jihoonerd/Data_Structures_and_Algorithms_in_Python/88920c1cbdb655c5bfe18ad3e74624d6745ab625/images/improper_tree.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | argon2-cffi==21.3.0
2 | argon2-cffi-bindings==21.2.0
3 | asttokens==2.0.8
4 | attrs==22.1.0
5 | backcall==0.2.0
6 | beautifulsoup4==4.11.1
7 | bleach==5.0.1
8 | certifi==2024.7.4
9 | cffi==1.15.1
10 | chardet==3.0.4
11 | cycler==0.11.0
12 | dbus-python==1.2.16
13 | debugpy==1.6.3
14 | decorator==5.1.1
15 | defusedxml==0.7.1
16 | distro==1.4.0
17 | entrypoints==0.4
18 | executing==0.10.0
19 | fastjsonschema==2.16.1
20 | fonttools==4.43.0
21 | idna==3.7
22 | importlib-metadata==4.12.0
23 | importlib-resources==5.9.0
24 | ipykernel==6.15.1
25 | ipython==8.10.0
26 | ipython-genutils==0.2.0
27 | ipywidgets==8.0.1
28 | jedi==0.18.1
29 | Jinja2==3.1.6
30 | jsonschema==4.14.0
31 | jupyter==1.0.0
32 | jupyter-client==7.3.4
33 | jupyter-console==6.4.4
34 | jupyter-core==4.11.2
35 | jupyterlab-pygments==0.2.2
36 | jupyterlab-widgets==3.0.2
37 | kiwisolver==1.4.4
38 | lxml==4.9.1
39 | MarkupSafe==2.1.1
40 | matplotlib==3.5.3
41 | matplotlib-inline==0.1.6
42 | mistune==2.0.4
43 | nbclient==0.6.7
44 | nbconvert==7.0.0
45 | nbformat==5.4.0
46 | nest-asyncio==1.5.5
47 | notebook==6.4.12
48 | numpy==1.23.2
49 | packaging==21.3
50 | pandas==1.4.3
51 | pandocfilters==1.5.0
52 | parso==0.8.3
53 | pexpect==4.8.0
54 | pickleshare==0.7.5
55 | Pillow==10.3.0
56 | pkgutil_resolve_name==1.3.10
57 | prometheus-client==0.14.1
58 | prompt-toolkit==3.0.30
59 | psutil==5.9.1
60 | ptyprocess==0.7.0
61 | pure-eval==0.2.2
62 | pycparser==2.21
63 | Pygments==2.15.0
64 | PyGObject==3.36.0
65 | pyparsing==3.0.9
66 | pyrsistent==0.18.1
67 | python-dateutil==2.8.2
68 | pytz==2022.2.1
69 | pyzmq==23.2.1
70 | qtconsole==5.3.1
71 | QtPy==2.2.0
72 | requests==2.32.0
73 | scipy==1.10.0
74 | seaborn==0.11.2
75 | Send2Trash==1.8.0
76 | six==1.14.0
77 | soupsieve==2.3.2.post1
78 | ssh-import-id==5.10
79 | stack-data==0.4.0
80 | terminado==0.15.0
81 | tinycss2==1.1.1
82 | tornado==6.5.1
83 | traitlets==5.3.0
84 | ufw==0.36
85 | urllib3==1.26.19
86 | wcwidth==0.2.5
87 | webencodings==0.5.1
88 | widgetsnbextension==4.0.2
89 | zipp==3.19.1
90 |
--------------------------------------------------------------------------------