diff --git a/.gitpod.yml b/.gitpod.yml
index 26a7d2a..5a6941a 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -2,7 +2,8 @@ image:
file: .gitpod.Dockerfile
tasks:
- - init: pip install -r ./requirements.txt
+ - before: sudo apt-get install -y graphviz
+ init: pip install -r ./requirements.txt
vscode:
extensions:
diff --git a/Algorithm/algviz/BubbleSort.ipynb b/Algorithm/algviz/BubbleSort.ipynb
new file mode 100644
index 0000000..510a254
--- /dev/null
+++ b/Algorithm/algviz/BubbleSort.ipynb
@@ -0,0 +1,99 @@
+{
+ "cells": [
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Bubble sort algorithm\n",
+ "\n",
+ "## Description\n",
+ "\n",
+ "The [bubble sort algorithm](https://en.wikipedia.org/wiki/Bubble_sort) compares the size of two adjacent elements in turn during each round of scanning and if the two elements are in reverse order, the algorithm swaps the positions of the two elements. Suppose the algorithm scans from left to right, and each time it puts the larger of the two adjacent elements in the right. Then after this round of scanning, the maximum value in the scanned sequence will run to the far right of the scanned sequence. The bubble sort algorithm repeats the scanning process until all the elements are sorted.\n",
+ "\n",
+ "The bubble sort algorithm is also a comparison-based sorting algorithm and the sorting results are stable. The bubble sort algorithm needs $O(n^2)$ comparison operations regardless of the sequence of the input data. Therefore, in some cases, the algorithm is not as efficient as the insertion sort algorithm. And for large-scale cases, the bubble sort algorithm also donesβt have any advantage except for its simplicity.\n",
+ "\n",
+ "You can try to change the `input_nums` and see how this algorithm works on different input.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*\n",
+ "\n",
+ "## Reference\n",
+ "\n",
+ "https://algviz.com/en/BubbleSort/"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "def bubble_sort(data):\n",
+ " viz = algviz.Visualizer(0.5)\n",
+ " vector = viz.createVector(data, cell_size=(40, 160), histogram=True)\n",
+ " for i in range(len(vector)):\n",
+ " for j in range(len(vector)-i-1):\n",
+ " if vector[j] > vector[j+1]:\n",
+ " vector.mark(algviz.cRed, j)\n",
+ " vector.mark(algviz.cGreen, j+1)\n",
+ " viz.display()\n",
+ " vector.swap(j, j+1)\n",
+ " else:\n",
+ " vector.mark(algviz.cRed, j+1)\n",
+ " vector.mark(algviz.cGreen, j)\n",
+ " viz.display()\n",
+ " vector.mark(algviz.cGray, len(vector)-i-1, hold=True)\n",
+ " vector.removeMark(algviz.cGray)\n",
+ " viz.display()\n",
+ "\n",
+ "input_nums = [5, 4, -2, 1, -1, 3]\n",
+ "bubble_sort(input_nums)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.16"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/Dijkstra.ipynb b/Algorithm/algviz/Dijkstra.ipynb
new file mode 100644
index 0000000..a1b72c3
--- /dev/null
+++ b/Algorithm/algviz/Dijkstra.ipynb
@@ -0,0 +1,332 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Dijkstra\n",
+ "\n",
+ "## Optimal substructure\n",
+ "\n",
+ "**The shortest path between two nodes contains other shortest paths.**\n",
+ "\n",
+ "## Inputs\n",
+ "\n",
+ "+ The input graph should be **directed graph**.\n",
+ "+ All the edge weights should be **no negative**.\n",
+ "+ The source node id in the graph.\n",
+ "\n",
+ "## Auxiliary data structure\n",
+ "\n",
+ "+ `shortest_path_table:` stores the shortest path dist and the predecessor node in the shortest path from source node to all the nodes in graph.\n",
+ "\n",
+ "## Outputs\n",
+ "\n",
+ "+ The list of all the shortest path from the source node to the other nodes in the graph.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "class DjkstraSolver:\n",
+ " def __init__(self, nodes, edges, source):\n",
+ " self._nodes_num = len(nodes)\n",
+ " self._viz = algviz.Visualizer(4, 1, layout=True)\n",
+ " self._graph_nodes = algviz.parseGraph(nodes, edges)\n",
+ " self._graph = self._viz.createGraph(self._graph_nodes, 'Graph')\n",
+ " self._log = self._viz.createLogger(1, show_line_num=False)\n",
+ " self._log2 = self._viz.createLogger(3, show_line_num=False)\n",
+ " self._shortest_path_table = self._viz.createTable(3, self._nodes_num+1,\n",
+ " [[i-1 for i in range(self._nodes_num+1)], ['βΎ' for _ in range(self._nodes_num+1)],\n",
+ " [None for _ in range(self._nodes_num+1)]], 'shortest_path_table', show_index=False)\n",
+ " self._shortest_path_table[0][0] = 'node'\n",
+ " self._shortest_path_table[1][0] = 'dist'\n",
+ " self._shortest_path_table[2][0] = 'pred'\n",
+ " self._source_node = self._graph_nodes[source]\n",
+ " self._shortest_path_table[1][self._source_node.val+1] = 0\n",
+ " self._visited_nodes = set()\n",
+ "\n",
+ " def run(self):\n",
+ " self._viz.display()\n",
+ " while len(self._visited_nodes) < self._nodes_num:\n",
+ " node, dist = self.extract_min()\n",
+ " self._graph.markNode(algviz.color_tan, node, True)\n",
+ " self._shortest_path_table.mark(algviz.color_tan, 0, node.val+1, True)\n",
+ " self._log.write('Current shortest path: {} -> ... -> {}'.format(self._source_node.val, node.val))\n",
+ " self._viz.display(0.5)\n",
+ " for (neighbor, edge) in node.neighbors():\n",
+ " neighbor_dist = self._shortest_path_table[1][neighbor.val+1]\n",
+ " self._graph.markNode(algviz.color_green_yellow, neighbor, True)\n",
+ " self._shortest_path_table.mark(algviz.color_green_yellow, 0, neighbor.val+1, True)\n",
+ " if node != self._source_node:\n",
+ " self.mark_min_path(neighbor, algviz.color_aqua)\n",
+ " self._log2.write('{} -> ... -> {} current minimum distance: {}'.format(\n",
+ " self._source_node.val, neighbor.val, neighbor_dist))\n",
+ " self._viz.display()\n",
+ " self.mark_min_path(node, algviz.color_pink)\n",
+ " self._graph.markEdge(algviz.color_pink, node, neighbor)\n",
+ " self._log2.write('{} -> ... -> {} -> ... -> {} distance: {}'.format(\n",
+ " self._source_node.val, node.val, neighbor.val, dist + edge))\n",
+ " self._viz.display()\n",
+ " if neighbor_dist == 'βΎ' or dist + edge < neighbor_dist:\n",
+ " self._shortest_path_table[1][neighbor.val+1] = dist + edge\n",
+ " self._shortest_path_table[2][neighbor.val+1] = node.val\n",
+ " self._shortest_path_table.mark(algviz.color_pink, 1, neighbor.val+1)\n",
+ " self._shortest_path_table.mark(algviz.color_pink, 2, neighbor.val+1)\n",
+ " self._log2.write('Update the shortest path of node: {}'.format(neighbor.val))\n",
+ " self._viz.display(1)\n",
+ " self._graph.removeMark(algviz.color_green_yellow)\n",
+ " self._shortest_path_table.removeMark(algviz.color_green_yellow)\n",
+ " self._viz.display(1)\n",
+ " self._graph.removeMark(algviz.color_tan)\n",
+ " self._shortest_path_table.removeMark(algviz.color_tan)\n",
+ " self._viz.display(); self._viz.layout()\n",
+ "\n",
+ " def extract_min(self):\n",
+ " min_dist, min_index = None, None\n",
+ " for i in range(self._nodes_num):\n",
+ " dist = self._shortest_path_table[1][i+1]\n",
+ " if i not in self._visited_nodes and dist != 'βΎ' and (\n",
+ " min_dist == None or dist < min_dist):\n",
+ " min_dist = dist\n",
+ " min_index = i\n",
+ " self._visited_nodes.add(min_index)\n",
+ " return self._graph_nodes[min_index], min_dist\n",
+ "\n",
+ " def mark_min_path(self, node, color):\n",
+ " pred = self._shortest_path_table[2][node.val+1]\n",
+ " while pred != None and node != self._source_node:\n",
+ " pred_node = self._graph_nodes[pred]\n",
+ " self._graph.markNode(color, pred_node)\n",
+ " self._graph.markEdge(color, pred_node, node)\n",
+ " node = pred_node\n",
+ " pred = self._shortest_path_table[2][node.val+1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "image/svg+xml": {
+ "duration": 143.5,
+ "frames": 45,
+ "layout": {
+ "9": [
+ 5,
+ 5,
+ 444,
+ 193
+ ],
+ "10": [
+ 454,
+ 157,
+ 275,
+ 16
+ ],
+ "11": [
+ 454,
+ 178,
+ 312,
+ 47
+ ],
+ "12": [
+ 454,
+ 5,
+ 329,
+ 147
+ ]
+ },
+ "size": [
+ 788,
+ 230
+ ]
+ }
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Test case1.\n",
+ "nodes = [0, 1, 2, 3, 4, 5, 6]\n",
+ "edges = [(0, 1, 2), (0, 6, 6), (0, 4, 8),\n",
+ " (1, 2, 3), (1, 5, 1),\n",
+ " (2, 3, 1),\n",
+ " (3, 4, 3),\n",
+ " (5, 3, 2), (5, 6, 1), (5, 2, 1),\n",
+ " (6, 4, 3)]\n",
+ "DjkstraSolver(nodes, edges, 0).run()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "2014362231131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131016223231413101622323141310162232314131Current shortest path: 4 -> ... -> 4Current shortest path: 4 -> ... -> 4Current shortest path: 4 -> ... -> 4Current shortest path: 4 -> ... -> 4Current shortest path: 4 -> ... -> 4Current shortest path: 4 -> ... -> 1Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 0Current shortest path: 4 -> ... -> 2Current shortest path: 4 -> ... -> 2Current shortest path: 4 -> ... -> 2Current shortest path: 4 -> ... -> 2Current shortest path: 4 -> ... -> 2Current shortest path: 4 -> ... -> 2Current shortest path: 4 -> ... -> 2Current shortest path: 4 -> ... -> 3Current shortest path: 4 -> ... -> 3Current shortest path: 4 -> ... -> 3Current shortest path: 4 -> ... -> 3Current shortest path: 4 -> ... -> 3Update the shortest path of node: 0Update the shortest path of node: 0Update the shortest path of node: 0Update the shortest path of node: 1Update the shortest path of node: 0Update the shortest path of node: 1Update the shortest path of node: 0Update the shortest path of node: 1Update the shortest path of node: 0Update the shortest path of node: 1Update the shortest path of node: 0Update the shortest path of node: 14 -> ... -> 1 current minimum distance: 1Update the shortest path of node: 14 -> ... -> 1 current minimum distance: 14 -> ... -> 0 -> ... -> 1 distance: 9Update the shortest path of node: 14 -> ... -> 1 current minimum distance: 14 -> ... -> 0 -> ... -> 1 distance: 94 -> ... -> 1 current minimum distance: 14 -> ... -> 0 -> ... -> 1 distance: 94 -> ... -> 2 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 1 distance: 94 -> ... -> 2 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 2 distance: 54 -> ... -> 2 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 2 distance: 5Update the shortest path of node: 24 -> ... -> 2 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 2 distance: 5Update the shortest path of node: 24 -> ... -> 0 -> ... -> 2 distance: 5Update the shortest path of node: 24 -> ... -> 3 current minimum distance: βΎUpdate the shortest path of node: 24 -> ... -> 3 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 3 distance: 54 -> ... -> 3 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 3 distance: 5Update the shortest path of node: 34 -> ... -> 3 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 3 distance: 5Update the shortest path of node: 34 -> ... -> 3 current minimum distance: βΎ4 -> ... -> 0 -> ... -> 3 distance: 5Update the shortest path of node: 34 -> ... -> 0 -> ... -> 3 distance: 5Update the shortest path of node: 34 -> ... -> 1 current minimum distance: 1Update the shortest path of node: 34 -> ... -> 1 current minimum distance: 14 -> ... -> 2 -> ... -> 1 distance: 8Update the shortest path of node: 34 -> ... -> 1 current minimum distance: 14 -> ... -> 2 -> ... -> 1 distance: 84 -> ... -> 1 current minimum distance: 14 -> ... -> 2 -> ... -> 1 distance: 84 -> ... -> 3 current minimum distance: 54 -> ... -> 2 -> ... -> 1 distance: 84 -> ... -> 3 current minimum distance: 54 -> ... -> 2 -> ... -> 3 distance: 64 -> ... -> 2 -> ... -> 1 distance: 84 -> ... -> 3 current minimum distance: 54 -> ... -> 2 -> ... -> 3 distance: 64 -> ... -> 2 -> ... -> 1 distance: 84 -> ... -> 3 current minimum distance: 54 -> ... -> 2 -> ... -> 3 distance: 64 -> ... -> 3 current minimum distance: 54 -> ... -> 2 -> ... -> 3 distance: 64 -> ... -> 4 current minimum distance: 04 -> ... -> 2 -> ... -> 3 distance: 64 -> ... -> 4 current minimum distance: 04 -> ... -> 3 -> ... -> 4 distance: 64 -> ... -> 2 -> ... -> 3 distance: 64 -> ... -> 4 current minimum distance: 04 -> ... -> 3 -> ... -> 4 distance: 64 -> ... -> 2 -> ... -> 3 distance: 64 -> ... -> 4 current minimum distance: 04 -> ... -> 3 -> ... -> 4 distance: 6-1node01234βΎdistβΎβΎβΎβΎβΎ0prednode01234distβΎβΎβΎβΎ0prednode01234distβΎ3βΎβΎβΎ0pred4node01234dist3βΎβΎβΎ0pred4node01234dist3βΎ1βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎβΎ0pred44node01234dist31βΎ5βΎ0pred440node01234dist315βΎ0pred440node01234dist315βΎ0pred440node01234dist315βΎ0pred440node01234dist315βΎ50pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400node01234dist31550pred4400 Make your Python code alive A L Z G V I Graph:shortest_path_table:"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "image/svg+xml": {
+ "duration": 104.5,
+ "frames": 31,
+ "layout": {
+ "14": [
+ 5,
+ 5,
+ 364,
+ 169
+ ],
+ "15": [
+ 374,
+ 157,
+ 275,
+ 16
+ ],
+ "16": [
+ 374,
+ 178,
+ 312,
+ 47
+ ],
+ "17": [
+ 374,
+ 5,
+ 249,
+ 147
+ ]
+ },
+ "size": [
+ 691,
+ 230
+ ]
+ }
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Test case2, graph with cycle.\n",
+ "nodes = [0, 1, 2, 3, 4]\n",
+ "edges = [(0, 1, 6), (0, 2, 2), (0, 3, 2),\n",
+ " (2, 1, 3), (2, 3, 1),\n",
+ " (3, 4, 1),\n",
+ " (4, 0, 3), (4, 1, 1)]\n",
+ "DjkstraSolver(nodes, edges, 4).run()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "02111-301121-301121-301121-301121-301121-301121-301121-301121-301121-301121-301121-301121-301121-301121-3Current shortest path: 0 -> ... -> 0Current shortest path: 0 -> ... -> 0Current shortest path: 0 -> ... -> 0Current shortest path: 0 -> ... -> 1Current shortest path: 0 -> ... -> 1Current shortest path: 0 -> ... -> 1Current shortest path: 0 -> ... -> 1Current shortest path: 0 -> ... -> 1Current shortest path: 0 -> ... -> 2Current shortest path: 0 -> ... -> 2Current shortest path: 0 -> ... -> 2Current shortest path: 0 -> ... -> 2Current shortest path: 0 -> ... -> 2Current shortest path: 0 -> ... -> 2Update the shortest path of node: 1Update the shortest path of node: 1Update the shortest path of node: 1Update the shortest path of node: 10 -> ... -> 2 current minimum distance: βΎUpdate the shortest path of node: 10 -> ... -> 2 current minimum distance: βΎ0 -> ... -> 1 -> ... -> 2 distance: 20 -> ... -> 2 current minimum distance: βΎ0 -> ... -> 1 -> ... -> 2 distance: 2Update the shortest path of node: 20 -> ... -> 2 current minimum distance: βΎ0 -> ... -> 1 -> ... -> 2 distance: 2Update the shortest path of node: 20 -> ... -> 2 current minimum distance: βΎ0 -> ... -> 1 -> ... -> 2 distance: 2Update the shortest path of node: 20 -> ... -> 1 -> ... -> 2 distance: 2Update the shortest path of node: 20 -> ... -> 0 current minimum distance: 0Update the shortest path of node: 20 -> ... -> 0 current minimum distance: 00 -> ... -> 2 -> ... -> 0 distance: -10 -> ... -> 0 current minimum distance: 00 -> ... -> 2 -> ... -> 0 distance: -1Update the shortest path of node: 00 -> ... -> 0 current minimum distance: 00 -> ... -> 2 -> ... -> 0 distance: -1Update the shortest path of node: 00 -> ... -> 0 current minimum distance: 00 -> ... -> 2 -> ... -> 0 distance: -1Update the shortest path of node: 0-1node012βΎdistβΎ0βΎβΎprednode012dist0βΎβΎprednode012dist0βΎ1βΎpred0node012dist01βΎpred0node012dist01βΎpred0node012dist01βΎpred0node012dist01βΎpred0node012dist01βΎ2pred01node012dist012pred01node012dist012pred01node012dist012pred01node012dist012pred01node012dist0-112pred201node012dist-112pred201node012dist-112pred201 Make your Python code alive A L Z G V I Graph:shortest_path_table:"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "image/svg+xml": {
+ "duration": 49.5,
+ "frames": 15,
+ "layout": {
+ "19": [
+ 393,
+ 56,
+ 204,
+ 95
+ ],
+ "20": [
+ 322,
+ 5,
+ 275,
+ 16
+ ],
+ "21": [
+ 5,
+ 5,
+ 312,
+ 47
+ ],
+ "22": [
+ 602,
+ 5,
+ 169,
+ 145.5
+ ]
+ },
+ "size": [
+ 776,
+ 174
+ ]
+ }
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Test case3, failed when there exist a cycle with negative edge value.\n",
+ "nodes = [0, 1, 2]\n",
+ "edges = [(0, 1, 1), (1, 2, 1), (2, 0, -3)]\n",
+ "DjkstraSolver(nodes, edges, 0).run()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.16"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/DisjointSet.ipynb b/Algorithm/algviz/DisjointSet.ipynb
new file mode 100644
index 0000000..cec6186
--- /dev/null
+++ b/Algorithm/algviz/DisjointSet.ipynb
@@ -0,0 +1,238 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Disjoint-set\n",
+ "\n",
+ "Disjoint-set(also called union-find set) is a special data structure for checking if two elements belong to the same set and merging two sets into one.\n",
+ "\n",
+ "## Disjoint-set forest\n",
+ "\n",
+ "If we put each element into one set, then we get a disjoint-set forest, this is the initial state.\n",
+ "\n",
+ "Each element maintains a reference that pointer to its parent element. If the pointer is null, then this element is the root of the set it belongs to. Initially, all the potiners are null.\n",
+ "\n",
+ "## Find\n",
+ "\n",
+ "At this step, we find the root element of a given element. The root element stands for the set of the given element belongs to.\n",
+ "\n",
+ "## Union\n",
+ "\n",
+ "Merge two sets into one set. Usually, we give two elements which belongs to two sets, then the algorithm merge one set into another set.\n",
+ "\n",
+ "## Optimize\n",
+ "\n",
+ "If the set tree is unbalanced, the find operation will cost a lot of time. So, we can do the path compression during the find operation. That is, we set all the references of all the elements in the query path to the root element of the set.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "class DisjointSet:\n",
+ " def __init__(self, nums):\n",
+ " self.viz = algviz.Visualizer(1, layout=True)\n",
+ " self.sets = self.viz.createGraph()\n",
+ " self.log1 = self.viz.createLogger(1, None, 16, False)\n",
+ " self.log2 = self.viz.createLogger(1, None, 16, False)\n",
+ " self.num2elem = dict()\n",
+ " for x in nums:\n",
+ " elem = algviz.TreeNode(x)\n",
+ " self.num2elem[x] = elem\n",
+ " self.sets.addNode(elem)\n",
+ " elem.parent = None\n",
+ " self.viz.display()\n",
+ "\n",
+ " def find(self, x):\n",
+ " elem = self.num2elem[x]\n",
+ " self.sets.markNode(algviz.cLime, elem)\n",
+ " self.viz.display(0.5)\n",
+ " if elem.parent == None:\n",
+ " self.sets.markNode(algviz.cTomato, elem, True)\n",
+ " self.viz.display(0.5)\n",
+ " return elem.val\n",
+ " else:\n",
+ " res = self.find(elem.parent.val)\n",
+ " new_parent = self.num2elem[res]\n",
+ " if elem.parent != new_parent:\n",
+ " self.log2.write('Compress path: {} -> {}'.format(elem.val, new_parent.val))\n",
+ " elem.parent.remove(elem)\n",
+ " elem.parent = new_parent\n",
+ " elem.parent.add(elem)\n",
+ " self.viz.display()\n",
+ " self.log2.write('')\n",
+ " return res\n",
+ "\n",
+ " def union(self, x, y):\n",
+ " self.log1.write('Union: {} <=> {}'.format(x, y))\n",
+ " root1 = self.num2elem[self.find(x)]\n",
+ " root2 = self.num2elem[self.find(y)]\n",
+ " self.sets.removeMark(algviz.cTomato)\n",
+ " if root1 != root2:\n",
+ " root1.parent = root2\n",
+ " root2.add(root1)\n",
+ " self.viz.display()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You can try to change the numbers in the `elements` and the union operations in the `union_list` to see what will happen."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "31402012340123401234012340123401234012340123401234012340123401234012340123401234013240132401324013240132401324013240132401324Union: 0 <=> 1Union: 0 <=> 1Union: 0 <=> 1Union: 0 <=> 1Union: 0 <=> 1Union: 2 <=> 3Union: 2 <=> 3Union: 2 <=> 3Union: 2 <=> 3Union: 2 <=> 3Union: 3 <=> 1Union: 3 <=> 1Union: 3 <=> 1Union: 3 <=> 1Union: 3 <=> 1Union: 4 <=> 2Union: 4 <=> 2Union: 4 <=> 2Union: 4 <=> 2Union: 4 <=> 2Union: 4 <=> 2Union: 4 <=> 2Union: 4 <=> 2Union: 4 <=> 2Compress path: 2 -> 1 Make your Python code alive A L Z G V I "
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "image/svg+xml": {
+ "duration": 31.5,
+ "frames": 25,
+ "layout": {
+ "0": [
+ 5,
+ 57,
+ 260,
+ 188
+ ],
+ "1": [
+ 5,
+ 31,
+ 145,
+ 21
+ ],
+ "2": [
+ 5,
+ 5,
+ 215,
+ 21
+ ]
+ },
+ "size": [
+ 270,
+ 250
+ ]
+ }
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "elements = [0, 1, 2, 3, 4]\n",
+ "union_list = [(0, 1), (2, 3), (3, 1), (4, 2)]\n",
+ "diset = DisjointSet(elements)\n",
+ "for (x, y) in union_list:\n",
+ " diset.union(x, y)\n",
+ "diset.viz.layout(300)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "416728593001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345879601234587960123458796012345879601234587960123458796012345879601234587960123458796Union: 0 <=> 1Union: 0 <=> 1Union: 0 <=> 1Union: 0 <=> 1Union: 0 <=> 1Union: 2 <=> 3Union: 2 <=> 3Union: 2 <=> 3Union: 2 <=> 3Union: 2 <=> 3Union: 4 <=> 3Union: 4 <=> 3Union: 4 <=> 3Union: 4 <=> 3Union: 4 <=> 3Union: 0 <=> 4Union: 0 <=> 4Union: 0 <=> 4Union: 0 <=> 4Union: 0 <=> 4Union: 0 <=> 4Union: 0 <=> 4Union: 0 <=> 4Union: 0 <=> 4Union: 7 <=> 8Union: 7 <=> 8Union: 7 <=> 8Union: 7 <=> 8Union: 7 <=> 8Union: 9 <=> 8Union: 9 <=> 8Union: 9 <=> 8Union: 9 <=> 8Union: 9 <=> 8Union: 9 <=> 5Union: 9 <=> 5Union: 9 <=> 5Union: 9 <=> 5Union: 9 <=> 5Union: 9 <=> 5Union: 9 <=> 5Union: 7 <=> 6Union: 7 <=> 6Union: 7 <=> 6Union: 7 <=> 6Union: 7 <=> 6Union: 7 <=> 6Union: 7 <=> 6Union: 7 <=> 6Union: 7 <=> 6Compress path: 7 -> 5 Make your Python code alive A L Z G V I "
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "image/svg+xml": {
+ "duration": 61,
+ "frames": 51,
+ "layout": {
+ "4": [
+ 5,
+ 31,
+ 530,
+ 260
+ ],
+ "5": [
+ 225,
+ 5,
+ 145,
+ 21
+ ],
+ "6": [
+ 5,
+ 5,
+ 215,
+ 21
+ ]
+ },
+ "size": [
+ 540,
+ 296
+ ]
+ }
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "elements = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
+ "union_list = [\n",
+ " (0, 1), (2, 3), (4, 3), (0, 4), # Set0: (0, 1, 2, 3, 4)\n",
+ " (7, 8), (9, 8), (9, 5), (7, 6) # Set1: (5, 6, 7, 8, 9)\n",
+ "]\n",
+ "diset = DisjointSet(elements)\n",
+ "for (x, y) in union_list:\n",
+ " diset.union(x, y)\n",
+ "diset.viz.layout(600)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.16"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/Fibonacci.ipynb b/Algorithm/algviz/Fibonacci.ipynb
new file mode 100644
index 0000000..ee16b80
--- /dev/null
+++ b/Algorithm/algviz/Fibonacci.ipynb
@@ -0,0 +1,256 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# What is a fibonacci number?\n",
+ "\n",
+ "The Fibonacci numbers may be defined by the recurrence relation:\n",
+ "\n",
+ "$F_{0}=0$, $F_{1}=1$ and $F_{n}=F_{n-1}+F_{n-2}$\n",
+ "\n",
+ "This is the first ten numbers in fibonacci sequence:\n",
+ "\n",
+ "> 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...\n",
+ "\n",
+ "Reference: https://en.wikipedia.org/wiki/Fibonacci_number\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Solution\n",
+ "\n",
+ "The code is simple and intuitive.\n",
+ "\n",
+ "We just need to implement the recurrence relation as below:\n",
+ "\n",
+ "```python\n",
+ "def fib(n):\n",
+ " if n <= 1:\n",
+ " return n\n",
+ " return fib(n-1) + fib(n-2)\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Visualization\n",
+ "\n",
+ "We use the [RecursiveTree](https://algviz.com/en/RecursiveTree/) in algviz to show the recursive animation of this algorithm."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "class FibViz:\n",
+ " def __init__(self) -> None:\n",
+ " self.viz = algviz.Visualizer(1)\n",
+ " name = \"Fibonacci Recursive Tree\"\n",
+ " self.tree = algviz.RecursiveTree(self.viz, name)\n",
+ "\n",
+ " def fib(self, n):\n",
+ " self.tree.forward('fib({})'.format(n)); self.viz.display()\n",
+ " if n <= 1:\n",
+ " self.tree.backward(n); self.viz.display()\n",
+ " return n\n",
+ " res = self.fib(n-1) + self.fib(n-2)\n",
+ " self.tree.backward(res); self.viz.display()\n",
+ " return res"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Fibonacci Recursive Tree:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "fib(2)110Generated by algviz-0.3.0(see https://algviz.com)."
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Fib(2)= 1\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('Fib(2)=', FibViz().fib(2))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Fibonacci Recursive Tree:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "fib(3)21110Generated by algviz-0.3.0(see https://algviz.com)."
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Fib(3)= 2\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('Fib(3)=', FibViz().fib(3))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Fibonacci Recursive Tree:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "fib(4)321111010Generated by algviz-0.3.0(see https://algviz.com)."
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Fib(4)= 3\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('Fib(4)=', FibViz().fib(4))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Fibonacci Recursive Tree:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "fib(5)532211110101110Generated by algviz-0.3.0(see https://algviz.com)."
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Fib(5)= 5\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('Fib(5)=', FibViz().fib(5))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.16"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/MergeSort.ipynb b/Algorithm/algviz/MergeSort.ipynb
new file mode 100644
index 0000000..c0ae0c3
--- /dev/null
+++ b/Algorithm/algviz/MergeSort.ipynb
@@ -0,0 +1,193 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Merge sort algorithm\n",
+ "\n",
+ "## Introduction\n",
+ "\n",
+ "The merge sort algorithm uses the idea of divide and conquer, which reduces the big things to small ones and solves the small thing recursively, then gather the solutions together! The idea of divide and conquer includes the divide, resolve, and merge processes.\n",
+ "\n",
+ "1. Divide: divide the sequence to be sorted into two subsequences (usually from the middle).\n",
+ "2. Resolve: call the resolve function recursively on subsequences until the subsequence can be sorted directly.\n",
+ "3. Merge: merge the sorted subsequences to get the sorting solution of the parent sequence.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*\n",
+ "\n",
+ "## References\n",
+ "\n",
+ "+ https://algviz.com/en/MergeSort/\n",
+ "+ https://algviz.com/en/RecursiveTree/"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "class MergeSort():\n",
+ " def __init__(self, nums_):\n",
+ " self.viz = algviz.Visualizer(2.0)\n",
+ " self.nums = self.viz.createVector(nums_, name='Numbers', cell_size=(40, 200), histogram=True)\n",
+ " self.merge_list = self.viz.createVector(name='Merge list', show_index=False)\n",
+ " self.tree = algviz.RecursiveTree(self.viz)\n",
+ " self.solve(0, len(nums_))\n",
+ " \n",
+ " def solve(self, l, r):\n",
+ " if l < r - 1:\n",
+ " self.tree.forward('{}:{}'.format(l, r))\n",
+ " m = (l + r)//2\n",
+ " self.solve(l, m)\n",
+ " self.solve(m, r)\n",
+ " self.nums.mark(algviz.color_gray, 0, l, hold=True)\n",
+ " if r < len(self.nums):\n",
+ " self.nums.mark(algviz.color_gray, r, len(self.nums), hold=True)\n",
+ " self.merge(l, m, r)\n",
+ " self.tree.backward()\n",
+ " self.nums.removeMark(algviz.color_gray)\n",
+ " \n",
+ " def merge(self, l, m, r):\n",
+ " # Take out the smaller elements in the subsequence in turn and place them in the merge_list.\n",
+ " ll = l; mm = m\n",
+ " self.viz.display()\n",
+ " while ll < m and mm < r:\n",
+ " if self.nums[ll] > self.nums[mm]:\n",
+ " self.merge_list.append(self.nums[mm])\n",
+ " self.nums.mark(algviz.color_gold, mm); self.nums.mark(algviz.color_dark_green, ll)\n",
+ " self.merge_list.mark(algviz.color_gold, len(self.merge_list)-1); self.viz.display()\n",
+ " mm += 1; self.viz.display(1)\n",
+ " else:\n",
+ " self.merge_list.append(self.nums[ll])\n",
+ " self.nums.mark(algviz.color_gold, ll); self.nums.mark(algviz.color_dark_green, mm)\n",
+ " self.merge_list.mark(algviz.color_gold, len(self.merge_list)-1); self.viz.display()\n",
+ " ll += 1; self.viz.display(1)\n",
+ " while ll < m:\n",
+ " self.merge_list.append(self.nums[ll])\n",
+ " self.nums.mark(algviz.color_gold, ll)\n",
+ " self.merge_list.mark(algviz.color_gold, len(self.merge_list)-1); self.viz.display()\n",
+ " ll += 1; self.viz.display(1)\n",
+ " while mm < r:\n",
+ " self.merge_list.append(self.nums[mm])\n",
+ " self.nums.mark(algviz.color_gold, mm)\n",
+ " self.merge_list.mark(algviz.color_gold, len(self.merge_list)-1); self.viz.display()\n",
+ " mm += 1; self.viz.display(1)\n",
+ " # Copies the merge_list into the origin subsequence to be resolved.\n",
+ " self.viz.display()\n",
+ " for i in range(l, r):\n",
+ " self.merge_list.mark(algviz.color_spring_green, 0)\n",
+ " self.nums[i] = self.merge_list.pop(0)\n",
+ " self.nums.mark(algviz.color_spring_green, i)\n",
+ " self.viz.display()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Numbers:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "Generated by algviz-0.2.2(see https://algviz.com).-2-11334450123456"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "Merge list:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "Generated by algviz-0.2.2(see https://algviz.com).5"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "Recursive tree:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "0:70:33:71:33:55:7Generated by algviz-0.2.2(see https://algviz.com)."
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "input_nums = [5, 3, -2, 3, -1, 1, 4]\n",
+ "solver = MergeSort(input_nums)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.13"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/NQueens.ipynb b/Algorithm/algviz/NQueens.ipynb
new file mode 100644
index 0000000..8721f8c
--- /dev/null
+++ b/Algorithm/algviz/NQueens.ipynb
@@ -0,0 +1,124 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Description\n",
+ "\n",
+ "This notebook shows the algorithm running process to solves the [NQueens](https://leetcode.com/problems/n-queens/) problem.\n",
+ "\n",
+ "You can try to change the size of the checkerboard(**N**) and see the algorithm's backtracking process.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "Generated by algviz-0.2.2(see https://algviz.com).πβ01230123rc"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import algviz\n",
+ "N = 4 # The size of the checkerboard\n",
+ "viz = algviz.Visualizer(1)\n",
+ "board = viz.createTable(N, N)\n",
+ "cursor_row = viz.createCursor(name='r')\n",
+ "cursor_col = viz.createCursor(name='c')\n",
+ "board[cursor_row][cursor_col]\n",
+ "\n",
+ "def draw_board_background():\n",
+ " for r in range(N):\n",
+ " for c in range(N):\n",
+ " if (r + c) % 2:\n",
+ " board.mark(algviz.color_gray, r, c, True)\n",
+ "\n",
+ "def solve_queen(queen_row_pos, col_has_queen, cur_row):\n",
+ " if cur_row == N:\n",
+ " for r in range(N):\n",
+ " board.mark(algviz.color_green, r, queen_row_pos[r])\n",
+ " viz.display(3)\n",
+ " return\n",
+ " cursor_row << cur_row\n",
+ " for c in range(0, N):\n",
+ " cursor_col << c\n",
+ " board[cur_row][c] = 'β'\n",
+ " viz.display()\n",
+ " if col_has_queen[c] == False:\n",
+ " conflict = False\n",
+ " for r in range(0, cur_row):\n",
+ " if queen_row_pos[r] - c == r - cur_row or c - queen_row_pos[r] == r - cur_row:\n",
+ " board.mark(algviz.color_red, r, queen_row_pos[r])\n",
+ " board.mark(algviz.color_red, cur_row, c)\n",
+ " viz.display(0.5)\n",
+ " conflict = True\n",
+ " break\n",
+ " if not conflict:\n",
+ " queen_row_pos[cur_row] = c\n",
+ " col_has_queen[c] = True\n",
+ " board[cur_row][c] = 'π'\n",
+ " viz.display()\n",
+ " solve_queen(queen_row_pos, col_has_queen, cur_row+1)\n",
+ " col_has_queen[c] = False\n",
+ " board[cur_row][c] = ''\n",
+ " cursor_row << cur_row\n",
+ " else:\n",
+ " board[cur_row][c] = ''\n",
+ " else:\n",
+ " for r in range(cur_row):\n",
+ " if queen_row_pos[r] == c:\n",
+ " board.mark(algviz.color_red, r, c)\n",
+ " break\n",
+ " board.mark(algviz.color_red, cur_row, c)\n",
+ " viz.display(0.5)\n",
+ " board[cur_row][c] = ''\n",
+ "\n",
+ "draw_board_background()\n",
+ "solve_queen([-1 for _ in range(N)], [False for _ in range(N)], 0)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.13"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/Prim.ipynb b/Algorithm/algviz/Prim.ipynb
new file mode 100644
index 0000000..9412808
--- /dev/null
+++ b/Algorithm/algviz/Prim.ipynb
@@ -0,0 +1,201 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Prim algorithm\n",
+ "\n",
+ "**Prim's algorithm is a greedy algorithm that finds a [minimum spanning tree](https://en.wikipedia.org/wiki/Minimum_spanning_tree) for a weighted undirected graph.**\n",
+ "\n",
+ "The algorithm consists of the following steps:\n",
+ "\n",
+ "1. Initialize a tree with a single vertex, chosen arbitrarily from the graph.\n",
+ "\n",
+ "2. Grow the tree by one edge: of the edges that connect the tree to vertices not yet in the tree, find the minimum-weight edge, and transfer it to the tree.\n",
+ "\n",
+ "3. Repeat step 2 (until all vertices are in the tree).\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*\n",
+ "\n",
+ "## Reference\n",
+ "\n",
+ "https://en.wikipedia.org/wiki/Prim%27s_algorithm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "class PrimAlgorithm:\n",
+ " def __init__(self, graph_nodes):\n",
+ " self.viz = algviz.Visualizer(0.5)\n",
+ " self.graph = self.viz.createGraph(graph_nodes, name='Input graph', directed=False)\n",
+ " self.nodes_num = len(graph_nodes)\n",
+ " self.graph_nodes = graph_nodes\n",
+ " self.tree_nodes = list()\n",
+ " for node in graph_nodes.values():\n",
+ " self.tree_nodes.append(node)\n",
+ " self.graph.markNode(algviz.cTomato, node, True)\n",
+ " break\n",
+ " self.viz.display()\n",
+ "\n",
+ " def solve(self):\n",
+ " used_edges = list()\n",
+ " while len(self.tree_nodes) < self.nodes_num:\n",
+ " min_edge = None; min_node1 = None; min_node2 = None\n",
+ " for node in self.tree_nodes:\n",
+ " for (neighbor, edge) in node.neighbors():\n",
+ " if neighbor not in self.tree_nodes:\n",
+ " if min_edge == None or edge < min_edge:\n",
+ " min_edge = edge\n",
+ " min_node1 = node; min_node2 = neighbor\n",
+ " if min_edge == None:\n",
+ " return False\n",
+ " self.graph.markNode(algviz.cTomato, min_node2, True)\n",
+ " self.graph.markEdge(algviz.cRed, min_node1, min_node2, True)\n",
+ " used_edges.append((min_node1, min_node2))\n",
+ " self.tree_nodes.append(min_node2)\n",
+ " self.viz.display()\n",
+ " self.graph.removeMark(algviz.cTomato)\n",
+ " for node in self.graph_nodes.values():\n",
+ " for (neighbor, edge) in node.neighbors():\n",
+ " if (node, neighbor) not in used_edges:\n",
+ " node.remove(neighbor)\n",
+ " self.viz.display(3)\n",
+ " return True"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Input graph:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "012233462Generated by algviz-0.2.2(see https://algviz.com).232"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "nodes1 = [i for i in range(4)]\n",
+ "edges1 = [(0, 1, 2), (0, 3, 4), (2, 1, 3), (2, 3, 2), (3, 1, 6)]\n",
+ "graph_nodes1 = algviz.parseGraph(nodes1, edges1, directed=False)\n",
+ "\n",
+ "solver1 = PrimAlgorithm(graph_nodes1)\n",
+ "solver1.solve()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Input graph:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "025321663553728454493721Generated by algviz-0.2.2(see https://algviz.com).221423334"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "\n",
+ "nodes2 = [i for i in range(10)]\n",
+ "edges2 = [\n",
+ " (0, 1, 6), (0, 2, 5), (0, 3, 2), (2, 4, 4), (6, 5, 3),\n",
+ " (1, 6, 3), (2, 7, 5), (3, 8, 2), (3, 9, 1), (7, 6, 2),\n",
+ " (4, 8 ,7), (7, 8, 4), (9, 2, 3), (5, 1, 5)\n",
+ "]\n",
+ "graph_nodes2 = algviz.parseGraph(nodes2, edges2, directed=False)\n",
+ "\n",
+ "solver2 = PrimAlgorithm(graph_nodes2)\n",
+ "solver2.solve()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.13"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/QuickSort.ipynb b/Algorithm/algviz/QuickSort.ipynb
new file mode 100644
index 0000000..595c0e4
--- /dev/null
+++ b/Algorithm/algviz/QuickSort.ipynb
@@ -0,0 +1,140 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Quick sort algorithm\n",
+ "\n",
+ "## Description\n",
+ "\n",
+ "The Quicksort algorithm was first proposed by Charles Antony Richard Hoare, also called the partition-exchange sort algorithm.\n",
+ "The Quicksort algorithm has high execution efficiency in general and is widely used in practical engineering.\n",
+ "For more description, please refer to this [blog](https://algviz.com/en/QuickSort/#fundamental).\n",
+ "\n",
+ "You can try to change the `input_nums` and run the cells below.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "class QuickSort():\n",
+ " def __init__(self, nums_):\n",
+ " self.viz = algviz.Visualizer(1.0, layout=True)\n",
+ " self.nums = self.viz.createVector(nums_, name='Numbers', cell_size=(40,200), histogram=True)\n",
+ " self.tree = algviz.RecursiveTree(self.viz)\n",
+ " self.p = self.viz.createCursor(name='P'); self.nums[self.p]\n",
+ " self.solve(0, len(nums_))\n",
+ " self.viz.display(3.0); self.viz.layout()\n",
+ " \n",
+ " def solve(self, l, r):\n",
+ " if l >= r - 1:\n",
+ " return # Basic situation: just one element left in the subsequence.\n",
+ " self.tree.forward('{}:{}'.format(l, r-1))\n",
+ " self.nums.mark(algviz.color_gray, 0, l, hold=True)\n",
+ " if r < len(self.nums):\n",
+ " self.nums.mark(algviz.color_gray, r, len(self.nums), hold=True)\n",
+ " i = l; self.p << l; self.viz.display()\n",
+ " # Subsequence segmentation beigin.\n",
+ " while i < r - 1:\n",
+ " if self.nums[i] < self.nums[r-1]:\n",
+ " self.nums.mark(algviz.color_orange, r-1); self.nums.mark(algviz.color_tomato, i); self.viz.display(1.0)\n",
+ " self.nums.swap(i, self.p); self.viz.display(2.0)\n",
+ " self.nums.mark(algviz.color_silver, self.p, hold=True); self.p += 1\n",
+ " else:\n",
+ " self.nums.mark(algviz.color_orange, r-1); self.nums.mark(algviz.color_lime, i); self.viz.display()\n",
+ " self.nums.mark(algviz.color_silver, i, hold=True)\n",
+ " i += 1; self.viz.display(1.0)\n",
+ " self.nums.swap(self.p, r-1); self.viz.display(2.0)\n",
+ " # Subsequence segmentation end.\n",
+ " self.nums.removeMark(algviz.color_gray); self.nums.removeMark(algviz.color_silver)\n",
+ " self.solve(l, self.p.index())\n",
+ " self.solve(self.p + 1, r)\n",
+ " self.tree.backward()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P3-4-14-6-320123456P0:60:60:60:60:60:60:60:60:60:60:60:60:60:60:60:60:60:60:60:30:60:30:60:30:60:30:60:30:60:30:60:30:60:30:60:30:60:30:60:30:10:60:30:10:60:30:10:60:30:10:60:30:11:30:60:30:11:30:60:30:11:30:60:30:11:30:60:30:11:30:60:30:11:30:60:30:11:30:60:30:11:30:60:30:11:31:20:60:30:11:31:20:60:30:11:31:20:60:30:11:31:20:60:30:11:31:20:60:30:11:31:23:60:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:20:60:33:60:11:31:23:40:60:33:60:11:31:23:40:60:33:60:11:31:23:40:60:33:60:11:31:23:40:60:33:60:11:31:23:40:60:33:60:11:31:23:45:60:60:33:60:11:31:23:45:60:60:33:60:11:31:23:45:60:60:33:60:11:31:23:45:60:60:33:60:11:31:23:45:60:60:33:60:11:31:23:45:6 Make your Python code alive A L Z G V I Numbers:Recursive tree:"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "image/svg+xml": {
+ "duration": 125,
+ "frames": 66,
+ "layout": {
+ "0": [
+ 5,
+ 5,
+ 304,
+ 237
+ ],
+ "1": [
+ 314,
+ 5,
+ 226,
+ 278
+ ]
+ },
+ "size": [
+ 545,
+ 306
+ ]
+ }
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "input_nums = [3, -4, -1, 4, -6, -3, 2]\n",
+ "solver = QuickSort(input_nums)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.16"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/ReverseLinkedList.ipynb b/Algorithm/algviz/ReverseLinkedList.ipynb
new file mode 100644
index 0000000..f61225f
--- /dev/null
+++ b/Algorithm/algviz/ReverseLinkedList.ipynb
@@ -0,0 +1,98 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Reverse linked list\n",
+ "\n",
+ "Solve the leetcode problem [reverse-linked-list](https://leetcode.com/problems/reverse-linked-list/).\n",
+ "\n",
+ "## Solution\n",
+ "\n",
+ "Scan the linked list from head to tail.\n",
+ "\n",
+ "Use the `h1` and `h2` pointers to record the two adjacent nodes.\n",
+ "\n",
+ "Do the \"h2->h2\" to \"h1<-h2\" operation while scanning.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "1234567Generated by algviz-0.2.2(see https://algviz.com)."
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "def reverse_linked_list(data):\n",
+ " # Create a visualizer object.\n",
+ " viz = algviz.Visualizer(1)\n",
+ " # Create and display a forward linked list.\n",
+ " head = algviz.parseForwardLinkedList(data)\n",
+ " graph = viz.createGraph(head)\n",
+ " viz.display(1)\n",
+ " # before h1->h2, after h1<-h2\n",
+ " h1 = None\n",
+ " h2 = head\n",
+ " while h2 is not None:\n",
+ " temp = h2.next\n",
+ " h2.next = h1\n",
+ " h1 = h2\n",
+ " h2 = temp\n",
+ " graph.markNode(algviz.cGold, h1)\n",
+ " graph.markNode(algviz.cAqua, h2)\n",
+ " viz.display()\n",
+ " viz.display()\n",
+ "\n",
+ "data = [1, 2, 3, 4, 5, 6, 7]\n",
+ "reverse_linked_list(data)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.13"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Algorithm/algviz/TrieTree.ipynb b/Algorithm/algviz/TrieTree.ipynb
new file mode 100644
index 0000000..44529ec
--- /dev/null
+++ b/Algorithm/algviz/TrieTree.ipynb
@@ -0,0 +1,214 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# TrieTree\n",
+ "\n",
+ "This notebook shows how to construct a [trie tree](https://en.wikipedia.org/wiki/Trie) with a list of known strings and then shows how to use the trie tree to match a given string.\n",
+ "\n",
+ "## How to run?\n",
+ "\n",
+ "All the animations in this notebook are rendered by the [algviz](https://algviz.com/) algorithm animation engine in real time. You can follow this [guidance](https://algviz.com/en/installation.html) to set up your local environment or run this repo on Gitpod directly.\n",
+ "\n",
+ "*If you meet any problem, please report an π[issue](https://github.com/zjl9959/algviz/issues)π here.*"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import algviz\n",
+ "\n",
+ "class TrieTree:\n",
+ " def __init__(self, str_list):\n",
+ " self.viz = algviz.Visualizer(1)\n",
+ " table_cols = 0\n",
+ " for s in str_list:\n",
+ " table_cols = max(table_cols, len(s))\n",
+ " self.table = self.viz.createTable(len(str_list), table_cols, str_list, 'String list to construct trie tree', cell_size=(20, 20))\n",
+ " self.root = algviz.TreeNode('root')\n",
+ " self.graph = self.viz.createGraph(self.root)\n",
+ " self.s = self.viz.createVector(name='String to match', cell_size=(20, 20))\n",
+ " self.construct(str_list)\n",
+ "\n",
+ " def construct(self, str_list):\n",
+ " for i in range(len(str_list)):\n",
+ " cur = self.root\n",
+ " for j in range(len(str_list[i])):\n",
+ " child_pos = None\n",
+ " for child in cur.children():\n",
+ " if str(child) == str_list[i][j]:\n",
+ " child_pos = child\n",
+ " break\n",
+ " if not child_pos:\n",
+ " child_pos = algviz.TreeNode(str_list[i][j])\n",
+ " cur.add(child_pos)\n",
+ " cur = child_pos\n",
+ " self.table.mark(algviz.cAqua, i, j)\n",
+ " self.graph.markNode(algviz.cAqua, cur)\n",
+ " self.viz.display()\n",
+ " self.viz.display()\n",
+ "\n",
+ " def match(self, s):\n",
+ " self.graph.removeMark(algviz.cLime)\n",
+ " self.s.clear()\n",
+ " for c in s:\n",
+ " self.s.append(c)\n",
+ " cur = self.root\n",
+ " i = 0\n",
+ " while i < len(s):\n",
+ " match = False\n",
+ " self.s.removeMark(algviz.cLime)\n",
+ " self.s.mark(algviz.cLime, i, True)\n",
+ " for child in cur.children():\n",
+ " if child.val == s[i]:\n",
+ " cur = child\n",
+ " i += 1\n",
+ " match = True\n",
+ " self.graph.markNode(algviz.cLime, cur, True)\n",
+ " self.viz.display()\n",
+ " break\n",
+ " else:\n",
+ " self.graph.markNode(algviz.cSilver, child)\n",
+ " self.viz.display(0.5)\n",
+ " if not match:\n",
+ " return False\n",
+ " return i == len(s)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "String list to construct trie tree:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "Generated by algviz-0.2.2(see https://algviz.com).abcabdbcdbce0123012"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "rootabbcdcdeGenerated by algviz-0.2.2(see https://algviz.com)."
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "String to match:"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "Generated by algviz-0.2.2(see https://algviz.com).012bca"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Construct a tire tree.\n",
+ "str_list = ['abc', 'abd', 'bcd', 'bce']\n",
+ "trie_tree = TrieTree(str_list)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Match str:abd result is:True\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Match a string: True case\n",
+ "s1 = 'abd'\n",
+ "print('Match str:{} result is:{}'.format(s1, trie_tree.match(s1)))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Match str:bca result is:False\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Match a string: False case\n",
+ "s2 = 'bca'\n",
+ "print('Match str:{} result is:{}'.format(s2, trie_tree.match(s2)))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.13"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "ba530876bec2e6283b9bacba891681e9dff395534db17e3ec46729d6d41aa6cf"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/requirements.txt b/requirements.txt
index 54de05f..4494aca 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,4 +12,5 @@ tabulate
scikit-fuzzy
pillow
beautifulsoup4
-skia-python
\ No newline at end of file
+skia-python
+algviz>=0.3.0
\ No newline at end of file