diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bb826d8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,89 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "map": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "any": "cpp", + "barrier": "cpp", + "bitset": "cpp", + "cfenv": "cpp", + "charconv": "cpp", + "cinttypes": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "coroutine": "cpp", + "csetjmp": "cpp", + "csignal": "cpp", + "cuchar": "cpp", + "list": "cpp", + "set": "cpp", + "unordered_set": "cpp", + "optional": "cpp", + "regex": "cpp", + "source_location": "cpp", + "future": "cpp", + "latch": "cpp", + "mutex": "cpp", + "ranges": "cpp", + "scoped_allocator": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "span": "cpp", + "stop_token": "cpp", + "syncstream": "cpp", + "thread": "cpp", + "typeindex": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/Delete-test.cpp b/Delete-test.cpp new file mode 100644 index 0000000..cc3f998 --- /dev/null +++ b/Delete-test.cpp @@ -0,0 +1,177 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +struct HEAP +{ + std::vector data; // 0-based: data[0] is root + int n; // number of elements + int capacity; + HEAP(int cap = 32) : data(cap, 0), n(0), capacity(cap) {} +}; + +typedef int ElemType; + +Array1DTracer heapTracer = Array1DTracer("堆的数组形式"); +LogTracer logger = LogTracer("运行日志"); +GraphTracer heapGraph = GraphTracer("最大堆").directed(false); + +bool HeapFull(HEAP &heap) +{ + return (heap.n >= heap.capacity); +} + +// 更新图形化的堆树视图(binary heap visual) +// 使用连续的数值 id (0..n-1),并把堆值作为 weight 显示 +void updateHeapGraph(HEAP &heap) +{ + int n = heap.n; + GraphTracer heapGraph_new = GraphTracer("最大堆").directed(false); + heapGraph = heapGraph_new; + Layout::setRoot(VerticalLayout({heapGraph, heapTracer, logger})); + if (n <= 0) return; + for (int i = 0; i < n; ++i) + { + heapGraph.addNode(heap.data[i]); + } + for (int i = 0; i < n; ++i) + { + int left = 2 * i + 1; + int right = 2 * i + 2; + if (left < n) + { + heapGraph.addEdge(heap.data[i], heap.data[left]); + heapGraph.addEdge(heap.data[left], heap.data[i]); + } + if (right < n) + { + heapGraph.addEdge(heap.data[i], heap.data[right]); + heapGraph.addEdge(heap.data[right], heap.data[i]); + } + } + heapGraph.layoutTree(heap.data[0]); + Tracer::delay(); +} + +// DeleteMax (0-based indices) following image logic: parent=0, child=1 +void DeleteMax(HEAP &heap) +{ + if (heap.n == 0) + { + logger.println("堆为空,无法删除元素"); + Tracer::delay(); + return; + } + + ElemType elem = heap.data[0]; + ElemType tmp = heap.data[heap.n - 1]; + // 可视化 + logger.println("删除最大元素: " + std::to_string(elem) + ",并替换堆顶元素"); + heapTracer.select(0); + heapGraph.select(heap.data[0]); + // heapGraph.select(heap.data[heap.n - 1]); + Tracer::delay(); + + heap.n = heap.n - 1; + + // put last at root (will percolate down) + heap.data[0] = tmp; + heapTracer.deselect(0); + heapTracer.patch(0, heap.data[0]); + heapTracer.patch(heap.n, std::string("-")); + updateHeapGraph(heap); + heapGraph.select(heap.data[0]); + Tracer::delay(); + + + heapTracer.depatch(0); + heapTracer.depatch(heap.n); + heapGraph.deselect(heap.data[0]); + Tracer::delay(); + + logger.println("堆顶元素被最后一个元素替换,开始下滤过程"); + Tracer::delay(); + + int parent = 0; + int child = 1; // left child of parent=0 + + while (child <= heap.n - 1) + { + // 找到更大的子结点 + if (child < heap.n - 1 && heap.data[child] < heap.data[child + 1]) + child = child + 1; + + // 可视化 + heapGraph.select(heap.data[child]); + heapTracer.select(child); + Tracer::delay(); + + if (tmp >= heap.data[child]) + { + heapGraph.deselect(heap.data[child]); + heapTracer.deselect(child); + break; + } + + // move child up + heap.data[parent] = heap.data[child]; + heapTracer.patch(parent, heap.data[parent]); + logger.println("下滤:将 " + std::to_string(heap.data[child]) + " 移到索引 " + std::to_string(parent)); + Tracer::delay(); + + heapTracer.depatch(parent); + heapGraph.deselect(child); + heapTracer.deselect(child); + + // move down the tree + parent = child; + child = 2 * parent + 1; + } + + // place tmp at its position + heap.data[parent] = tmp; + heapTracer.patch(parent, heap.data[parent]); + Tracer::delay(); + + // update graph and array visualization + updateHeapGraph(heap); + logger.println("删除完成: " + std::to_string(elem) + ",当前堆大小: " + std::to_string(heap.n)); + Tracer::delay(); +} + +int main() +{ + Layout::setRoot(VerticalLayout({heapGraph, heapTracer, logger})); + + HEAP heap(10); + std::vector init = {95, 87, 78, 65, 53, 31, 9, 45, 17, 23}; + heap.n = (int)init.size(); + for (int i = 0; i < heap.n; ++i) heap.data[i] = init[i]; + + // array tracer (index 0..capacity-1) + json arr = json::array(); + for (int i = 0; i < heap.capacity; ++i) + { + if (i < heap.n) arr.push_back(heap.data[i]); + else arr.push_back(std::string("-")); + } + heapTracer.set(arr); + + updateHeapGraph(heap); + heapGraph.layoutTree(heap.data[0]); + + Tracer::delay(); + + logger.println("进行一次 DeleteMax"); Tracer::delay(); + DeleteMax(heap); + + logger.println("再执行一次 DeleteMax"); Tracer::delay(); + DeleteMax(heap); + + logger.println("结束"); Tracer::delay(); + + return 0; +} diff --git a/Finished/BFS/BFS-Graph.cpp b/Finished/BFS/BFS-Graph.cpp new file mode 100644 index 0000000..a1af299 --- /dev/null +++ b/Finished/BFS/BFS-Graph.cpp @@ -0,0 +1,217 @@ +#include "algorithm-visualizer.h" +#include +#include +#include +#include + +using json = nlohmann::json; + +// 从顶点 k 出发的一次 BFS +void BFSRec(const std::vector> &G, int k, + std::vector &visited, std::vector &dfn, int &count, + GraphTracer &graphTracer, Array2DTracer &tableTracer, Array1DTracer &queueTracer, LogTracer &logger) +{ + std::queue Q; + // 访问顶点 k + visited[k] = true; + dfn[k] = count++; + + // 可视化:标记并在表格中写入编号 + graphTracer.visit(k); + tableTracer.patch(1, k + 1, dfn[k]); + Tracer::delay(); + + tableTracer.depatch(1, k + 1); + Tracer::delay(); + + // 更新队列可视化(入队 k) + std::vector qview; + Q.push(k); + qview.push_back(k); + // 显示队列中实际内容(不限定长度),并记录长度变化 + json qjson = json::array(); + for (int x : qview) + qjson.push_back(x); + queueTracer.set(qjson); + logger.println(std::string("顶点 ") + std::to_string(k) + " 入队,队列大小= " + std::to_string((int)qview.size())); + graphTracer.leave(k); + graphTracer.select(k); + Tracer::delay(); + + while (!Q.empty()) + { + int v = Q.front(); + Q.pop(); + + queueTracer.select(0); // 高亮队首 + Tracer::delay(); + queueTracer.deselect(0); + Tracer::delay(); + // 更新队列可视化(出队): remove front from qview + if (!qview.empty()) + { + qview.erase(qview.begin()); + } + json qjson2 = json::array(); + for (int x : qview) + qjson2.push_back(x); + queueTracer.set(qjson2); + logger.println(std::string("顶点 ") + std::to_string(v) + " 出队,队列大小= " + std::to_string((int)qview.size())); + Tracer::delay(); + // 可视化:高亮当前出队的节点 + graphTracer.visit(v); + Tracer::delay(); + + // 遍历 v 的所有邻接点 + for (int w = 0; w < (int)G.size(); ++w) + { + if (G[v][w]) + { + if (visited[w]) + { + logger.println(std::string("顶点 ") + std::to_string(w) + " 已访问,跳过"); + Tracer::delay(); + continue; + } + // 可视化经过边 (v,w) + graphTracer.visit(v, w); + Tracer::delay(); + if (!visited[w]) + { + // 访问顶点 w + visited[w] = true; + dfn[w] = count++; + // 在表格里同步填写 dfn + tableTracer.patch(1, w + 1, dfn[w]); + Tracer::delay(); + tableTracer.depatch(1, w + 1); + graphTracer.select(w); + Tracer::delay(); + + // 将 w 入队并在图上标记 + Q.push(w); + qview.push_back(w); + // 更新队列显示(仅显示实际元素)并记录长度 + json qjson3 = json::array(); + for (int x : qview) + qjson3.push_back(x); + queueTracer.set(qjson3); + logger.println(std::string("顶点 ") + std::to_string(w) + " 入队,队列大小= " + std::to_string((int)qview.size())); + graphTracer.select(w); + Tracer::delay(); + graphTracer.deselect(w); + Tracer::delay(); + } + // 取消临时访问高亮 + graphTracer.leave(v, w); + Tracer::delay(); + } + } + // 取消当前节点的持久选中 + graphTracer.leave(v); + Tracer::delay(); + } +} + +// 主算法 +void BFSTraverse(const std::vector> &G, + GraphTracer &graphTracer, Array2DTracer &tableTracer, Array1DTracer &queueTracer, LogTracer &logger) +{ + int n = (int)G.size(); + std::vector visited(n, false); + std::vector dfn(n, 0); + int count = 1; + + logger.println("从顶点 0 开始图的广度优先遍历"); + Tracer::delay(); + BFSRec(G, 0, visited, dfn, count, graphTracer, tableTracer, queueTracer, logger); + + // 输出连通性判断 + bool connected = true; + for (int i = 0; i < n; ++i) + if (!visited[i]) + { + connected = false; + break; + } + if (connected) + logger.println("所有顶点都已遍历,该图连通"); + else + logger.println("存在未遍历的顶点,该图不连通"); + Tracer::delay(); + + // 若图不连通,可尝试对剩余未访问顶点再调用BFS,用于其余目的(保证遍历全部连通分量) + // for (int i = 0; i < n; ++i) { + // if (!visited[i]) { + // BFSRec(G, i, visited, dfn, count, graphTracer, tableTracer, queueTracer, logger); + // } + // } +} + +int main() +{ + GraphTracer graphTracer = GraphTracer("BFS 图遍历").directed(false); + Array2DTracer tableTracer = Array2DTracer("广度优先编号"); + Array1DTracer queueTracer = Array1DTracer("队列 Q"); + LogTracer logger = LogTracer("运行日志"); + Layout::setRoot(VerticalLayout({graphTracer, tableTracer, queueTracer, logger})); + + // 固定示例图(无向)——便于测试和复现 + int N = 7; + json Gjson = json::array(); + for (int i = 0; i < N; ++i) + { + json row = json::array(); + for (int j = 0; j < N; ++j) + row.push_back(0); + Gjson.push_back(row); + } + auto addEdge = [&](int a, int b) + { if (a>=0 && a=0 && b> + std::vector> G; + for (size_t i = 0; i < Gjson.size(); ++i) + { + std::vector row; + for (size_t j = 0; j < Gjson[i].size(); ++j) + row.push_back((int)Gjson[i][j]); + G.push_back(row); + } + + // 调用 BFSTraverse + BFSTraverse(G, graphTracer, tableTracer, queueTracer, logger); + + return 0; +} diff --git a/Finished/BFS/BFS-Graph.exe b/Finished/BFS/BFS-Graph.exe new file mode 100755 index 0000000..c9411c7 Binary files /dev/null and b/Finished/BFS/BFS-Graph.exe differ diff --git a/Finished/BFS/BFS-Graph.json b/Finished/BFS/BFS-Graph.json new file mode 100644 index 0000000..478e8ed --- /dev/null +++ b/Finished/BFS/BFS-Graph.json @@ -0,0 +1 @@ +[{"args":["BFS 图遍历"],"key":"bj5hxmga","method":"GraphTracer"},{"args":[false],"key":"bj5hxmga","method":"directed"},{"args":["广度优先编号"],"key":"n4hyh972","method":"Array2DTracer"},{"args":["队列 Q"],"key":"cdphop8q","method":"Array1DTracer"},{"args":["运行日志"],"key":"7g93ip3u","method":"LogTracer"},{"args":[["bj5hxmga","n4hyh972","cdphop8q","7g93ip3u"]],"key":"h9z3qwaz","method":"VerticalLayout"},{"args":["h9z3qwaz"],"key":null,"method":"setRoot"},{"args":[[[0,1,1,1,1,0,0],[1,0,0,1,1,1,0],[1,0,0,0,0,1,1],[1,1,0,0,0,0,1],[1,1,0,0,0,0,1],[0,1,1,0,0,0,0],[0,0,1,1,1,0,0]]],"key":"bj5hxmga","method":"set"},{"args":[],"key":"bj5hxmga","method":"layoutCircle"},{"args":[[["顶点","0","1","2","3","4","5","6"],["广度优先编号","-","-","-","-","-","-","-"]]],"key":"n4hyh972","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["从顶点 0 开始图的广度优先遍历"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"bj5hxmga","method":"visit"},{"args":[1,1,1],"key":"n4hyh972","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"n4hyh972","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[[0]],"key":"cdphop8q","method":"set"},{"args":["顶点 0 入队,队列大小= 1"],"key":"7g93ip3u","method":"println"},{"args":[0],"key":"bj5hxmga","method":"leave"},{"args":[0],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[]],"key":"cdphop8q","method":"set"},{"args":["顶点 0 出队,队列大小= 0"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,2,2],"key":"n4hyh972","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"n4hyh972","method":"depatch"},{"args":[1],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[1]],"key":"cdphop8q","method":"set"},{"args":["顶点 1 入队,队列大小= 1"],"key":"7g93ip3u","method":"println"},{"args":[1],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"bj5hxmga","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,3,3],"key":"n4hyh972","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"n4hyh972","method":"depatch"},{"args":[2],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[1,2]],"key":"cdphop8q","method":"set"},{"args":["顶点 2 入队,队列大小= 2"],"key":"7g93ip3u","method":"println"},{"args":[2],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"bj5hxmga","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,4,4],"key":"n4hyh972","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"n4hyh972","method":"depatch"},{"args":[3],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[1,2,3]],"key":"cdphop8q","method":"set"},{"args":["顶点 3 入队,队列大小= 3"],"key":"7g93ip3u","method":"println"},{"args":[3],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"bj5hxmga","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,5,5],"key":"n4hyh972","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"n4hyh972","method":"depatch"},{"args":[4],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[1,2,3,4]],"key":"cdphop8q","method":"set"},{"args":["顶点 4 入队,队列大小= 4"],"key":"7g93ip3u","method":"println"},{"args":[4],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"bj5hxmga","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[2,3,4]],"key":"cdphop8q","method":"set"},{"args":["顶点 1 出队,队列大小= 3"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 0 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 3 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 4 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,6,6],"key":"n4hyh972","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"n4hyh972","method":"depatch"},{"args":[5],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[2,3,4,5]],"key":"cdphop8q","method":"set"},{"args":["顶点 5 入队,队列大小= 4"],"key":"7g93ip3u","method":"println"},{"args":[5],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"bj5hxmga","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[3,4,5]],"key":"cdphop8q","method":"set"},{"args":["顶点 2 出队,队列大小= 3"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 0 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 5 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,7,7],"key":"n4hyh972","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"n4hyh972","method":"depatch"},{"args":[6],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[3,4,5,6]],"key":"cdphop8q","method":"set"},{"args":["顶点 6 入队,队列大小= 4"],"key":"7g93ip3u","method":"println"},{"args":[6],"key":"bj5hxmga","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"bj5hxmga","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[4,5,6]],"key":"cdphop8q","method":"set"},{"args":["顶点 3 出队,队列大小= 3"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 0 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 1 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 6 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[5,6]],"key":"cdphop8q","method":"set"},{"args":["顶点 4 出队,队列大小= 2"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 0 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 1 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 6 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[6]],"key":"cdphop8q","method":"set"},{"args":["顶点 5 出队,队列大小= 1"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 1 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 2 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"cdphop8q","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[]],"key":"cdphop8q","method":"set"},{"args":["顶点 6 出队,队列大小= 0"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"bj5hxmga","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 2 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 3 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 4 已访问,跳过"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"bj5hxmga","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":["所有顶点都已遍历,该图连通"],"key":"7g93ip3u","method":"println"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/Finished/BFS/BFS-Tree.cpp b/Finished/BFS/BFS-Tree.cpp new file mode 100644 index 0000000..03745c5 --- /dev/null +++ b/Finished/BFS/BFS-Tree.cpp @@ -0,0 +1,217 @@ +#include "algorithm-visualizer.h" +#include +#include +#include +#include + +using json = nlohmann::json; + +// 从顶点 k 出发的一次 BFS +void BFSRec(const std::vector> &G, int k, + std::vector &visited, std::vector &dfn, int &count, + GraphTracer &graphTracer, Array2DTracer &tableTracer, Array1DTracer &queueTracer, LogTracer &logger) +{ + std::queue Q; + // 访问顶点 k + visited[k] = true; + dfn[k] = count++; + + // 可视化:标记并在表格中写入编号 + graphTracer.visit(k); + tableTracer.patch(1, k + 1, dfn[k]); + Tracer::delay(); + + tableTracer.depatch(1, k + 1); + Tracer::delay(); + + // 更新队列可视化(入队 k) + std::vector qview; + Q.push(k); + qview.push_back(k); + // 显示队列中实际内容(不限定长度),并记录长度变化 + json qjson = json::array(); + for (int x : qview) + qjson.push_back(x); + queueTracer.set(qjson); + logger.println(std::string("顶点 ") + std::to_string(k) + " 入队,队列大小= " + std::to_string((int)qview.size())); + graphTracer.leave(k); + graphTracer.select(k); + Tracer::delay(); + + while (!Q.empty()) + { + int v = Q.front(); + Q.pop(); + + queueTracer.select(0); // 高亮队首 + Tracer::delay(); + queueTracer.deselect(0); + Tracer::delay(); + // 更新队列可视化(出队): remove front from qview + if (!qview.empty()) + { + qview.erase(qview.begin()); + } + json qjson2 = json::array(); + for (int x : qview) + qjson2.push_back(x); + queueTracer.set(qjson2); + logger.println(std::string("顶点 ") + std::to_string(v) + " 出队,队列大小= " + std::to_string((int)qview.size())); + Tracer::delay(); + // 可视化:高亮当前出队的节点 + graphTracer.visit(v); + Tracer::delay(); + + // 遍历 v 的所有邻接点 + for (int w = 0; w < (int)G.size(); ++w) + { + if (G[v][w]) + { + if (visited[w]) + { + logger.println(std::string("顶点 ") + std::to_string(w) + " 已访问,跳过"); + Tracer::delay(); + continue; + } + // 可视化经过边 (v,w) + graphTracer.visit(v, w); + Tracer::delay(); + if (!visited[w]) + { + // 访问顶点 w + visited[w] = true; + dfn[w] = count++; + // 在表格里同步填写 dfn + tableTracer.patch(1, w + 1, dfn[w]); + Tracer::delay(); + tableTracer.depatch(1, w + 1); + graphTracer.select(w); + Tracer::delay(); + + // 将 w 入队并在图上标记 + Q.push(w); + qview.push_back(w); + // 更新队列显示(仅显示实际元素)并记录长度 + json qjson3 = json::array(); + for (int x : qview) + qjson3.push_back(x); + queueTracer.set(qjson3); + logger.println(std::string("顶点 ") + std::to_string(w) + " 入队,队列大小= " + std::to_string((int)qview.size())); + graphTracer.select(w); + Tracer::delay(); + graphTracer.deselect(w); + Tracer::delay(); + } + // 取消临时访问高亮 + graphTracer.leave(v, w); + Tracer::delay(); + } + } + // 取消当前节点的持久选中 + graphTracer.leave(v); + Tracer::delay(); + } +} + +// 主算法 +void BFSTraverse(const std::vector> &G, + GraphTracer &graphTracer, Array2DTracer &tableTracer, Array1DTracer &queueTracer, LogTracer &logger) +{ + int n = (int)G.size(); + std::vector visited(n, false); + std::vector dfn(n, 0); + int count = 1; + + logger.println("从顶点 0 开始图的广度优先遍历"); + Tracer::delay(); + BFSRec(G, 0, visited, dfn, count, graphTracer, tableTracer, queueTracer, logger); + + // 输出连通性判断 + bool connected = true; + for (int i = 0; i < n; ++i) + if (!visited[i]) + { + connected = false; + break; + } + if (connected) + logger.println("所有顶点都已遍历,该图连通"); + else + logger.println("存在未遍历的顶点,该图不连通"); + Tracer::delay(); + + // 若图不连通,可尝试对剩余未访问顶点再调用BFS,用于其余目的(保证遍历全部连通分量) + // for (int i = 0; i < n; ++i) { + // if (!visited[i]) { + // BFSRec(G, i, visited, dfn, count, graphTracer, tableTracer, queueTracer, logger); + // } + // } +} + +int main() +{ + GraphTracer graphTracer = GraphTracer("BFS 树遍历").directed(false); + Array2DTracer tableTracer = Array2DTracer("广度优先编号"); + Array1DTracer queueTracer = Array1DTracer("队列 Q"); + LogTracer logger = LogTracer("运行日志"); + Layout::setRoot(VerticalLayout({graphTracer, tableTracer, queueTracer, logger})); + + // 固定示例二叉树(无向)——便于测试和复现 + int N = 11; // 完备二叉树 11 个节点(0..10) + json Gjson = json::array(); + for (int i = 0; i < N; ++i) + { + json row = json::array(); + for (int j = 0; j < N; ++j) + row.push_back(0); + Gjson.push_back(row); + } + auto addEdge = [&](int a, int b) + { if (a>=0 && a=0 && b> + std::vector> G; + for (size_t i = 0; i < Gjson.size(); ++i) + { + std::vector row; + for (size_t j = 0; j < Gjson[i].size(); ++j) + row.push_back((int)Gjson[i][j]); + G.push_back(row); + } + + // 初始化队列可视化为空 + json qinit = json::array(); + queueTracer.set(qinit); + Tracer::delay(); + + // 调用 BFSTraverse + BFSTraverse(G, graphTracer, tableTracer, queueTracer, logger); + + return 0; +} diff --git a/Finished/BFS/BFS-Tree.exe b/Finished/BFS/BFS-Tree.exe new file mode 100755 index 0000000..bb72626 Binary files /dev/null and b/Finished/BFS/BFS-Tree.exe differ diff --git a/Finished/BFS/BFS-Tree.json b/Finished/BFS/BFS-Tree.json new file mode 100644 index 0000000..b10f5bc --- /dev/null +++ b/Finished/BFS/BFS-Tree.json @@ -0,0 +1 @@ +[{"args":["BFS 树遍历"],"key":"4jrdhgfx","method":"GraphTracer"},{"args":[false],"key":"4jrdhgfx","method":"directed"},{"args":["广度优先编号"],"key":"4jpe1dkg","method":"Array2DTracer"},{"args":["队列 Q"],"key":"on4ugyq7","method":"Array1DTracer"},{"args":["运行日志"],"key":"fe48c998","method":"LogTracer"},{"args":[["4jrdhgfx","4jpe1dkg","on4ugyq7","fe48c998"]],"key":"vacr57kv","method":"VerticalLayout"},{"args":["vacr57kv"],"key":null,"method":"setRoot"},{"args":[[[0,1,1,0,0,0,0,0,0,0,0],[1,0,0,1,1,0,0,0,0,0,0],[1,0,0,0,0,1,1,0,0,0,0],[0,1,0,0,0,0,0,1,1,0,0],[0,1,0,0,0,0,0,0,0,1,1],[0,0,1,0,0,0,0,0,0,0,0],[0,0,1,0,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,0,0],[0,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,1,0,0,0,0,0,0]]],"key":"4jrdhgfx","method":"set"},{"args":[],"key":"4jrdhgfx","method":"layoutTree"},{"args":[[["顶点","0","1","2","3","4","5","6","7","8","9","10"],["广度优先编号","-","-","-","-","-","-","-","-","-","-","-"]]],"key":"4jpe1dkg","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":[[]],"key":"on4ugyq7","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["从顶点 0 开始图的广度优先遍历"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"4jrdhgfx","method":"visit"},{"args":[1,1,1],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"4jpe1dkg","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[[0]],"key":"on4ugyq7","method":"set"},{"args":["顶点 0 入队,队列大小= 1"],"key":"fe48c998","method":"println"},{"args":[0],"key":"4jrdhgfx","method":"leave"},{"args":[0],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[]],"key":"on4ugyq7","method":"set"},{"args":["顶点 0 出队,队列大小= 0"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,2,2],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"4jpe1dkg","method":"depatch"},{"args":[1],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[1]],"key":"on4ugyq7","method":"set"},{"args":["顶点 1 入队,队列大小= 1"],"key":"fe48c998","method":"println"},{"args":[1],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,3,3],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"4jpe1dkg","method":"depatch"},{"args":[2],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[1,2]],"key":"on4ugyq7","method":"set"},{"args":["顶点 2 入队,队列大小= 2"],"key":"fe48c998","method":"println"},{"args":[2],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[2]],"key":"on4ugyq7","method":"set"},{"args":["顶点 1 出队,队列大小= 1"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 0 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,4,4],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"4jpe1dkg","method":"depatch"},{"args":[3],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[2,3]],"key":"on4ugyq7","method":"set"},{"args":["顶点 3 入队,队列大小= 2"],"key":"fe48c998","method":"println"},{"args":[3],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,5,5],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"4jpe1dkg","method":"depatch"},{"args":[4],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[2,3,4]],"key":"on4ugyq7","method":"set"},{"args":["顶点 4 入队,队列大小= 3"],"key":"fe48c998","method":"println"},{"args":[4],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[3,4]],"key":"on4ugyq7","method":"set"},{"args":["顶点 2 出队,队列大小= 2"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 0 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,6,6],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"4jpe1dkg","method":"depatch"},{"args":[5],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[3,4,5]],"key":"on4ugyq7","method":"set"},{"args":["顶点 5 入队,队列大小= 3"],"key":"fe48c998","method":"println"},{"args":[5],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,7,7],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"4jpe1dkg","method":"depatch"},{"args":[6],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[3,4,5,6]],"key":"on4ugyq7","method":"set"},{"args":["顶点 6 入队,队列大小= 4"],"key":"fe48c998","method":"println"},{"args":[6],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[4,5,6]],"key":"on4ugyq7","method":"set"},{"args":["顶点 3 出队,队列大小= 3"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 1 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,8,8],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,8],"key":"4jpe1dkg","method":"depatch"},{"args":[7],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[4,5,6,7]],"key":"on4ugyq7","method":"set"},{"args":["顶点 7 入队,队列大小= 4"],"key":"fe48c998","method":"println"},{"args":[7],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[7],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[3,8],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,9,9],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,9],"key":"4jpe1dkg","method":"depatch"},{"args":[8],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[4,5,6,7,8]],"key":"on4ugyq7","method":"set"},{"args":["顶点 8 入队,队列大小= 5"],"key":"fe48c998","method":"println"},{"args":[8],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[8],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[3,8],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[5,6,7,8]],"key":"on4ugyq7","method":"set"},{"args":["顶点 4 出队,队列大小= 4"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 1 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4,9],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,10,10],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,10],"key":"4jpe1dkg","method":"depatch"},{"args":[9],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[5,6,7,8,9]],"key":"on4ugyq7","method":"set"},{"args":["顶点 9 入队,队列大小= 5"],"key":"fe48c998","method":"println"},{"args":[9],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[9],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,9],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[4,10],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,11,11],"key":"4jpe1dkg","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,11],"key":"4jpe1dkg","method":"depatch"},{"args":[10],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[[5,6,7,8,9,10]],"key":"on4ugyq7","method":"set"},{"args":["顶点 10 入队,队列大小= 6"],"key":"fe48c998","method":"println"},{"args":[10],"key":"4jrdhgfx","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[10],"key":"4jrdhgfx","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,10],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[6,7,8,9,10]],"key":"on4ugyq7","method":"set"},{"args":["顶点 5 出队,队列大小= 5"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 2 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[7,8,9,10]],"key":"on4ugyq7","method":"set"},{"args":["顶点 6 出队,队列大小= 4"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 2 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[8,9,10]],"key":"on4ugyq7","method":"set"},{"args":["顶点 7 出队,队列大小= 3"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[7],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 3 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[7],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[9,10]],"key":"on4ugyq7","method":"set"},{"args":["顶点 8 出队,队列大小= 2"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[8],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 3 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[8],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[10]],"key":"on4ugyq7","method":"set"},{"args":["顶点 9 出队,队列大小= 1"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[9],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 4 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[9],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"on4ugyq7","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[[]],"key":"on4ugyq7","method":"set"},{"args":["顶点 10 出队,队列大小= 0"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[10],"key":"4jrdhgfx","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["顶点 4 已访问,跳过"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[10],"key":"4jrdhgfx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":["所有顶点都已遍历,该图连通"],"key":"fe48c998","method":"println"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/Finished/Binary-Tree-Traversal/InOrder.cpp b/Finished/Binary-Tree-Traversal/InOrder.cpp new file mode 100644 index 0000000..fdd88ed --- /dev/null +++ b/Finished/Binary-Tree-Traversal/InOrder.cpp @@ -0,0 +1,114 @@ +#include "algorithm-visualizer.h" +#include +#include +#include +#include + +using json = nlohmann::json; + +// 单独实现 InOrder 函数(中序:左 - 根 - 右) +void InOrder(int root, int parent, + const std::vector>& T, + GraphTracer &treeTracer, Array1DTracer &arrayTracer, LogTracer &logger, + int &index) +{ + if (root == -1) { + logger.println("该结点不存在,回溯中..."); + Tracer::delay(); + return; + } + // 输出访问信息 + logger.println(std::string("到达结点:") + std::to_string(root)); + treeTracer.visit(root, parent); + Tracer::delay(); + + // 访问左子树 + logger.println(std::string("访问 ") + std::to_string(root) + " 的左子树"); + Tracer::delay(); + InOrder(T[root][0], root, T, treeTracer, arrayTracer, logger, index); + + // 访问根 + logger.println(std::string("到达结点:") + std::to_string(root)); + Tracer::delay(); + + logger.println(std::string("打印结点:") + std::to_string(root)); + treeTracer.leave(root, parent); + arrayTracer.patch(index++, root); + Tracer::delay(); + + // 访问右子树 + logger.println(std::string("访问 ") + std::to_string(root) + " 的右子树"); + Tracer::delay(); + InOrder(T[root][1], root, T, treeTracer, arrayTracer, logger, index); + +} + +int main() +{ + // 邻接矩阵表示图 G(用于展示) + std::vector> G = { + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {1,0,1,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,1,0,0,1,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,1,0,0,0,0,0,1,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,1,0,1,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,1,0,0,0,1,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,1,0,1}, + {0,0,0,0,0,0,0,0,0,0,0,0,0} + }; + + // T[i] = {left, right} + std::vector> T = { + std::array{-1,-1}, + std::array{0,2}, + std::array{-1,-1}, + std::array{1,4}, + std::array{-1,-1}, + std::array{3,9}, + std::array{-1,-1}, + std::array{6,8}, + std::array{-1,-1}, + std::array{7,11}, + std::array{-1,-1}, + std::array{10,12}, + std::array{-1,-1} + }; + + // Tracers + GraphTracer treeTracer = GraphTracer("中序遍历"); + Array1DTracer arrayTracer = Array1DTracer("中序遍历结果打印"); + LogTracer logger = LogTracer("运行日志"); + + Layout::setRoot(VerticalLayout({treeTracer, arrayTracer, logger})); + + // convert G to json array2d 并设置到 tracer + json Gjson = json::array(); + for (auto &row : G) { + json r = json::array(); + for (int v : row) r.push_back(v); + Gjson.push_back(r); + } + treeTracer.set(Gjson); + treeTracer.layoutTree(5); + + // 初始化 arrayTracer + int n = (int)T.size(); + std::vector adisp(n); + for (int i = 0; i < n; ++i) adisp[i] = "-"; + arrayTracer.set(adisp); + Tracer::delay(); + + int index = 0; + + // 调用单独实现的 InOrder(从根 5 开始) + InOrder(5, -1, T, treeTracer, arrayTracer, logger, index); + + logger.println("中序遍历结束"); + + return 0; +} \ No newline at end of file diff --git a/Finished/Binary-Tree-Traversal/InOrder.exe b/Finished/Binary-Tree-Traversal/InOrder.exe new file mode 100755 index 0000000..a4b3da1 Binary files /dev/null and b/Finished/Binary-Tree-Traversal/InOrder.exe differ diff --git a/Finished/Binary-Tree-Traversal/InOrder.json b/Finished/Binary-Tree-Traversal/InOrder.json new file mode 100644 index 0000000..01ac0b2 --- /dev/null +++ b/Finished/Binary-Tree-Traversal/InOrder.json @@ -0,0 +1 @@ +[{"args":["中序遍历"],"key":"wnewjd0s","method":"GraphTracer"},{"args":["中序遍历结果打印"],"key":"91xcqj94","method":"Array1DTracer"},{"args":["运行日志"],"key":"kgftnodf","method":"LogTracer"},{"args":[["wnewjd0s","91xcqj94","kgftnodf"]],"key":"c6hwwy1l","method":"VerticalLayout"},{"args":["c6hwwy1l"],"key":null,"method":"setRoot"},{"args":[[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,0,1,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,1,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,1,0,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,0,0,0,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,1],[0,0,0,0,0,0,0,0,0,0,0,0,0]]],"key":"wnewjd0s","method":"set"},{"args":[5],"key":"wnewjd0s","method":"layoutTree"},{"args":[["-","-","-","-","-","-","-","-","-","-","-","-","-"]],"key":"91xcqj94","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:5"],"key":"kgftnodf","method":"println"},{"args":[5,-1],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 5 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:3"],"key":"kgftnodf","method":"println"},{"args":[3,5],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 3 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:1"],"key":"kgftnodf","method":"println"},{"args":[1,3],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 1 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:0"],"key":"kgftnodf","method":"println"},{"args":[0,1],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 0 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:0"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:0"],"key":"kgftnodf","method":"println"},{"args":[0,1],"key":"wnewjd0s","method":"leave"},{"args":[0,0],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 0 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:1"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:1"],"key":"kgftnodf","method":"println"},{"args":[1,3],"key":"wnewjd0s","method":"leave"},{"args":[1,1],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 1 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:2"],"key":"kgftnodf","method":"println"},{"args":[2,1],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 2 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:2"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:2"],"key":"kgftnodf","method":"println"},{"args":[2,1],"key":"wnewjd0s","method":"leave"},{"args":[2,2],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 2 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:3"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:3"],"key":"kgftnodf","method":"println"},{"args":[3,5],"key":"wnewjd0s","method":"leave"},{"args":[3,3],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 3 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:4"],"key":"kgftnodf","method":"println"},{"args":[4,3],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 4 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:4"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:4"],"key":"kgftnodf","method":"println"},{"args":[4,3],"key":"wnewjd0s","method":"leave"},{"args":[4,4],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 4 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:5"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:5"],"key":"kgftnodf","method":"println"},{"args":[5,-1],"key":"wnewjd0s","method":"leave"},{"args":[5,5],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 5 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:9"],"key":"kgftnodf","method":"println"},{"args":[9,5],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 9 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:7"],"key":"kgftnodf","method":"println"},{"args":[7,9],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 7 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:6"],"key":"kgftnodf","method":"println"},{"args":[6,7],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 6 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:6"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:6"],"key":"kgftnodf","method":"println"},{"args":[6,7],"key":"wnewjd0s","method":"leave"},{"args":[6,6],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 6 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:7"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:7"],"key":"kgftnodf","method":"println"},{"args":[7,9],"key":"wnewjd0s","method":"leave"},{"args":[7,7],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 7 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:8"],"key":"kgftnodf","method":"println"},{"args":[8,7],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 8 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:8"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:8"],"key":"kgftnodf","method":"println"},{"args":[8,7],"key":"wnewjd0s","method":"leave"},{"args":[8,8],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 8 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:9"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:9"],"key":"kgftnodf","method":"println"},{"args":[9,5],"key":"wnewjd0s","method":"leave"},{"args":[9,9],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 9 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:11"],"key":"kgftnodf","method":"println"},{"args":[11,9],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 11 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:10"],"key":"kgftnodf","method":"println"},{"args":[10,11],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 10 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:10"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:10"],"key":"kgftnodf","method":"println"},{"args":[10,11],"key":"wnewjd0s","method":"leave"},{"args":[10,10],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 10 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:11"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:11"],"key":"kgftnodf","method":"println"},{"args":[11,9],"key":"wnewjd0s","method":"leave"},{"args":[11,11],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 11 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:12"],"key":"kgftnodf","method":"println"},{"args":[12,11],"key":"wnewjd0s","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 12 的左子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:12"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:12"],"key":"kgftnodf","method":"println"},{"args":[12,11],"key":"wnewjd0s","method":"leave"},{"args":[12,12],"key":"91xcqj94","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 12 的右子树"],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"kgftnodf","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["中序遍历结束"],"key":"kgftnodf","method":"println"}] \ No newline at end of file diff --git a/Finished/Binary-Tree-Traversal/PostOrder.cpp b/Finished/Binary-Tree-Traversal/PostOrder.cpp new file mode 100644 index 0000000..4d1f3dc --- /dev/null +++ b/Finished/Binary-Tree-Traversal/PostOrder.cpp @@ -0,0 +1,110 @@ +#include "algorithm-visualizer.h" +#include +#include +#include +#include + +using json = nlohmann::json; + +// 单独实现 PostOrder 函数(后序:左 - 右 - 根) +void PostOrder(int root, int parent, + const std::vector>& T, + GraphTracer &treeTracer, Array1DTracer &arrayTracer, LogTracer &logger, + int &index) +{ + if (root == -1) { + logger.println("该结点不存在,回溯中..."); + Tracer::delay(); + return; + } + // 输出访问信息 + logger.println(std::string("到达结点:") + std::to_string(root)); + treeTracer.visit(root, parent); + Tracer::delay(); + + // 先访问左子树 + logger.println(std::string("访问 ") + std::to_string(root) + " 的左子树"); + Tracer::delay(); + PostOrder(T[root][0], root, T, treeTracer, arrayTracer, logger, index); + + // 然后访问右子树 + logger.println(std::string("访问 ") + std::to_string(root) + " 的右子树"); + Tracer::delay(); + PostOrder(T[root][1], root, T, treeTracer, arrayTracer, logger, index); + + logger.println(std::string("打印结点:") + std::to_string(root)); + treeTracer.leave(root, parent); + arrayTracer.patch(index++, root); + Tracer::delay(); +} + +int main() +{ + // 邻接矩阵表示图 G(用于展示) + std::vector> G = { + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {1,0,1,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,1,0,0,1,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,1,0,0,0,0,0,1,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,1,0,1,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,1,0,0,0,1,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,1,0,1}, + {0,0,0,0,0,0,0,0,0,0,0,0,0} + }; + + // T[i] = {left, right} + std::vector> T = { + std::array{-1,-1}, + std::array{0,2}, + std::array{-1,-1}, + std::array{1,4}, + std::array{-1,-1}, + std::array{3,9}, + std::array{-1,-1}, + std::array{6,8}, + std::array{-1,-1}, + std::array{7,11}, + std::array{-1,-1}, + std::array{10,12}, + std::array{-1,-1} + }; + + // Tracers + GraphTracer treeTracer = GraphTracer("后序遍历"); + Array1DTracer arrayTracer = Array1DTracer("后序遍历结果打印"); + LogTracer logger = LogTracer("运行日志"); + + Layout::setRoot(VerticalLayout({treeTracer, arrayTracer, logger})); + + // convert G to json array2d 并设置到 tracer + json Gjson = json::array(); + for (auto &row : G) { + json r = json::array(); + for (int v : row) r.push_back(v); + Gjson.push_back(r); + } + treeTracer.set(Gjson); + treeTracer.layoutTree(5); + + // 初始化 arrayTracer + int n = (int)T.size(); + std::vector adisp(n); + for (int i = 0; i < n; ++i) adisp[i] = "-"; + arrayTracer.set(adisp); + Tracer::delay(); + + int index = 0; + + // 调用单独实现的 PostOrder(从根 5 开始) + PostOrder(5, -1, T, treeTracer, arrayTracer, logger, index); + + logger.println("后序遍历结束"); + + return 0; +} + diff --git a/Finished/Binary-Tree-Traversal/PostOrder.exe b/Finished/Binary-Tree-Traversal/PostOrder.exe new file mode 100755 index 0000000..479e0a0 Binary files /dev/null and b/Finished/Binary-Tree-Traversal/PostOrder.exe differ diff --git a/Finished/Binary-Tree-Traversal/PostOrder.json b/Finished/Binary-Tree-Traversal/PostOrder.json new file mode 100644 index 0000000..ab4c408 --- /dev/null +++ b/Finished/Binary-Tree-Traversal/PostOrder.json @@ -0,0 +1 @@ +[{"args":["后序遍历"],"key":"adr7a75d","method":"GraphTracer"},{"args":["后序遍历结果打印"],"key":"9kfinj7a","method":"Array1DTracer"},{"args":["运行日志"],"key":"ul8zvj8x","method":"LogTracer"},{"args":[["adr7a75d","9kfinj7a","ul8zvj8x"]],"key":"5l5jmhlo","method":"VerticalLayout"},{"args":["5l5jmhlo"],"key":null,"method":"setRoot"},{"args":[[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,0,1,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,1,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,1,0,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,0,0,0,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,1],[0,0,0,0,0,0,0,0,0,0,0,0,0]]],"key":"adr7a75d","method":"set"},{"args":[5],"key":"adr7a75d","method":"layoutTree"},{"args":[["-","-","-","-","-","-","-","-","-","-","-","-","-"]],"key":"9kfinj7a","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:5"],"key":"ul8zvj8x","method":"println"},{"args":[5,-1],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 5 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:3"],"key":"ul8zvj8x","method":"println"},{"args":[3,5],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 3 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:1"],"key":"ul8zvj8x","method":"println"},{"args":[1,3],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 1 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:0"],"key":"ul8zvj8x","method":"println"},{"args":[0,1],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 0 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 0 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:0"],"key":"ul8zvj8x","method":"println"},{"args":[0,1],"key":"adr7a75d","method":"leave"},{"args":[0,0],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 1 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:2"],"key":"ul8zvj8x","method":"println"},{"args":[2,1],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 2 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 2 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:2"],"key":"ul8zvj8x","method":"println"},{"args":[2,1],"key":"adr7a75d","method":"leave"},{"args":[1,2],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:1"],"key":"ul8zvj8x","method":"println"},{"args":[1,3],"key":"adr7a75d","method":"leave"},{"args":[2,1],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 3 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:4"],"key":"ul8zvj8x","method":"println"},{"args":[4,3],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 4 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 4 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:4"],"key":"ul8zvj8x","method":"println"},{"args":[4,3],"key":"adr7a75d","method":"leave"},{"args":[3,4],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:3"],"key":"ul8zvj8x","method":"println"},{"args":[3,5],"key":"adr7a75d","method":"leave"},{"args":[4,3],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 5 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:9"],"key":"ul8zvj8x","method":"println"},{"args":[9,5],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 9 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:7"],"key":"ul8zvj8x","method":"println"},{"args":[7,9],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 7 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:6"],"key":"ul8zvj8x","method":"println"},{"args":[6,7],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 6 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 6 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:6"],"key":"ul8zvj8x","method":"println"},{"args":[6,7],"key":"adr7a75d","method":"leave"},{"args":[5,6],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 7 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:8"],"key":"ul8zvj8x","method":"println"},{"args":[8,7],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 8 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 8 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:8"],"key":"ul8zvj8x","method":"println"},{"args":[8,7],"key":"adr7a75d","method":"leave"},{"args":[6,8],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:7"],"key":"ul8zvj8x","method":"println"},{"args":[7,9],"key":"adr7a75d","method":"leave"},{"args":[7,7],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 9 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:11"],"key":"ul8zvj8x","method":"println"},{"args":[11,9],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 11 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:10"],"key":"ul8zvj8x","method":"println"},{"args":[10,11],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 10 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 10 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:10"],"key":"ul8zvj8x","method":"println"},{"args":[10,11],"key":"adr7a75d","method":"leave"},{"args":[8,10],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 11 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:12"],"key":"ul8zvj8x","method":"println"},{"args":[12,11],"key":"adr7a75d","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["访问 12 的左子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 12 的右子树"],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"ul8zvj8x","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:12"],"key":"ul8zvj8x","method":"println"},{"args":[12,11],"key":"adr7a75d","method":"leave"},{"args":[9,12],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:11"],"key":"ul8zvj8x","method":"println"},{"args":[11,9],"key":"adr7a75d","method":"leave"},{"args":[10,11],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:9"],"key":"ul8zvj8x","method":"println"},{"args":[9,5],"key":"adr7a75d","method":"leave"},{"args":[11,9],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:5"],"key":"ul8zvj8x","method":"println"},{"args":[5,-1],"key":"adr7a75d","method":"leave"},{"args":[12,5],"key":"9kfinj7a","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["后序遍历结束"],"key":"ul8zvj8x","method":"println"}] \ No newline at end of file diff --git a/Finished/Binary-Tree-Traversal/PreOrder.cpp b/Finished/Binary-Tree-Traversal/PreOrder.cpp new file mode 100644 index 0000000..caf5dc1 --- /dev/null +++ b/Finished/Binary-Tree-Traversal/PreOrder.cpp @@ -0,0 +1,109 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +// 单独实现 PreOrder 函数(中序:左 - 根 - 右) +void PreOrder(int root, int parent, + const std::vector>& T, + GraphTracer &treeTracer, Array1DTracer &arrayTracer, LogTracer &logger, + int &index) +{ + if (root == -1) { + logger.println("该结点不存在,回溯中..."); + Tracer::delay(); + return; + } + + // 输出访问信息 + logger.println(std::string("到达结点:") + std::to_string(root)); + treeTracer.visit(root, parent); + Tracer::delay(); + + logger.println(std::string("打印结点:") + std::to_string(root)); + treeTracer.leave(root, parent); + arrayTracer.patch(index++, root); + Tracer::delay(); + + // 访问左子树 + logger.println(std::string("访问 ") + std::to_string(root) + " 的左子树"); + Tracer::delay(); + PreOrder(T[root][0], root, T, treeTracer, arrayTracer, logger, index); + + // 访问右子树 + logger.println(std::string("访问 ") + std::to_string(root) + " 的右子树"); + Tracer::delay(); + PreOrder(T[root][1], root, T, treeTracer, arrayTracer, logger, index); +} + +int main() +{ + // 邻接矩阵表示图 G(用于展示) + std::vector> G = { + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {1,0,1,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,1,0,0,1,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,1,0,0,0,0,0,1,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,1,0,1,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,1,0,0,0,1,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,1,0,1}, + {0,0,0,0,0,0,0,0,0,0,0,0,0} + }; + + // T[i] = {left, right} + std::vector> T = { + std::array{-1,-1}, + std::array{0,2}, + std::array{-1,-1}, + std::array{1,4}, + std::array{-1,-1}, + std::array{3,9}, + std::array{-1,-1}, + std::array{6,8}, + std::array{-1,-1}, + std::array{7,11}, + std::array{-1,-1}, + std::array{10,12}, + std::array{-1,-1} + }; + + // Tracers + GraphTracer treeTracer = GraphTracer("先序遍历"); + Array1DTracer arrayTracer = Array1DTracer("先序遍历结果打印"); + LogTracer logger = LogTracer("运行日志"); + + Layout::setRoot(VerticalLayout({treeTracer, arrayTracer, logger})); + + // convert G to json array2d + json Gjson = json::array(); + for (auto &row : G) { + json r = json::array(); + for (int v : row) r.push_back(v); + Gjson.push_back(r); + } + treeTracer.set(Gjson); + treeTracer.layoutTree(5); + + // initialize arrayTracer with '-' entries + int n = (int)T.size(); + std::vector adisp(n); + for (int i = 0; i < n; ++i) adisp[i] = "-"; + arrayTracer.set(adisp); + Tracer::delay(); + + int index = 0; + + // start traversal from node 5 + PreOrder(5, -1, T, treeTracer, arrayTracer, logger, index); + + logger.println("先序遍历结束"); + + return 0; +} diff --git a/Finished/Binary-Tree-Traversal/PreOrder.exe b/Finished/Binary-Tree-Traversal/PreOrder.exe new file mode 100755 index 0000000..5774d32 Binary files /dev/null and b/Finished/Binary-Tree-Traversal/PreOrder.exe differ diff --git a/Finished/Binary-Tree-Traversal/PreOrder.json b/Finished/Binary-Tree-Traversal/PreOrder.json new file mode 100644 index 0000000..731a72f --- /dev/null +++ b/Finished/Binary-Tree-Traversal/PreOrder.json @@ -0,0 +1 @@ +[{"args":["先序遍历"],"key":"tdoyix1x","method":"GraphTracer"},{"args":["先序遍历结果打印"],"key":"jk2jpw4y","method":"Array1DTracer"},{"args":["运行日志"],"key":"656jauzy","method":"LogTracer"},{"args":[["tdoyix1x","jk2jpw4y","656jauzy"]],"key":"3c5iulos","method":"VerticalLayout"},{"args":["3c5iulos"],"key":null,"method":"setRoot"},{"args":[[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,0,1,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,1,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,1,0,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,0,0,0,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,1],[0,0,0,0,0,0,0,0,0,0,0,0,0]]],"key":"tdoyix1x","method":"set"},{"args":[5],"key":"tdoyix1x","method":"layoutTree"},{"args":[["-","-","-","-","-","-","-","-","-","-","-","-","-"]],"key":"jk2jpw4y","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:5"],"key":"656jauzy","method":"println"},{"args":[5,-1],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:5"],"key":"656jauzy","method":"println"},{"args":[5,-1],"key":"tdoyix1x","method":"leave"},{"args":[0,5],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 5 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:3"],"key":"656jauzy","method":"println"},{"args":[3,5],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:3"],"key":"656jauzy","method":"println"},{"args":[3,5],"key":"tdoyix1x","method":"leave"},{"args":[1,3],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 3 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:1"],"key":"656jauzy","method":"println"},{"args":[1,3],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:1"],"key":"656jauzy","method":"println"},{"args":[1,3],"key":"tdoyix1x","method":"leave"},{"args":[2,1],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 1 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:0"],"key":"656jauzy","method":"println"},{"args":[0,1],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:0"],"key":"656jauzy","method":"println"},{"args":[0,1],"key":"tdoyix1x","method":"leave"},{"args":[3,0],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 0 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 0 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 1 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:2"],"key":"656jauzy","method":"println"},{"args":[2,1],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:2"],"key":"656jauzy","method":"println"},{"args":[2,1],"key":"tdoyix1x","method":"leave"},{"args":[4,2],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 2 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 2 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 3 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:4"],"key":"656jauzy","method":"println"},{"args":[4,3],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:4"],"key":"656jauzy","method":"println"},{"args":[4,3],"key":"tdoyix1x","method":"leave"},{"args":[5,4],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 4 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 4 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 5 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:9"],"key":"656jauzy","method":"println"},{"args":[9,5],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:9"],"key":"656jauzy","method":"println"},{"args":[9,5],"key":"tdoyix1x","method":"leave"},{"args":[6,9],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 9 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:7"],"key":"656jauzy","method":"println"},{"args":[7,9],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:7"],"key":"656jauzy","method":"println"},{"args":[7,9],"key":"tdoyix1x","method":"leave"},{"args":[7,7],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 7 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:6"],"key":"656jauzy","method":"println"},{"args":[6,7],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:6"],"key":"656jauzy","method":"println"},{"args":[6,7],"key":"tdoyix1x","method":"leave"},{"args":[8,6],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 6 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 6 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 7 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:8"],"key":"656jauzy","method":"println"},{"args":[8,7],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:8"],"key":"656jauzy","method":"println"},{"args":[8,7],"key":"tdoyix1x","method":"leave"},{"args":[9,8],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 8 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 8 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 9 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:11"],"key":"656jauzy","method":"println"},{"args":[11,9],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:11"],"key":"656jauzy","method":"println"},{"args":[11,9],"key":"tdoyix1x","method":"leave"},{"args":[10,11],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 11 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:10"],"key":"656jauzy","method":"println"},{"args":[10,11],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:10"],"key":"656jauzy","method":"println"},{"args":[10,11],"key":"tdoyix1x","method":"leave"},{"args":[11,10],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 10 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 10 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 11 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["到达结点:12"],"key":"656jauzy","method":"println"},{"args":[12,11],"key":"tdoyix1x","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["打印结点:12"],"key":"656jauzy","method":"println"},{"args":[12,11],"key":"tdoyix1x","method":"leave"},{"args":[12,12],"key":"jk2jpw4y","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":["访问 12 的左子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["访问 12 的右子树"],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["该结点不存在,回溯中..."],"key":"656jauzy","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["先序遍历结束"],"key":"656jauzy","method":"println"}] \ No newline at end of file diff --git a/Finished/DFS/DFS-Graph.cpp b/Finished/DFS/DFS-Graph.cpp new file mode 100644 index 0000000..664bed5 --- /dev/null +++ b/Finished/DFS/DFS-Graph.cpp @@ -0,0 +1,126 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +// 递归实现的 DFS(与图片中的 DFS2 思路一致) +// G: 邻接矩阵(0/1),i: 当前访问顶点,parent: 父节点(-1 表示无) +// dfn: 深度优先编号数组,visited: 访问标记,cnt: 编号计数器(引用传递) +// graphTracer, tableTracer, logger 用于可视化 +void DFSRec(const std::vector> &G, int i, int parent, + std::vector &dfn, std::vector &visited, int &cnt, + GraphTracer &graphTracer, Array2DTracer &tableTracer, LogTracer &logger) +{ + // 访问顶点 i + visited[i] = true; + dfn[i] = ++cnt; + + // 可视化:标注节点(高亮访问)并在表格中填写编号 + if (parent >= 0) { + graphTracer.visit(i, parent); + } else { + graphTracer.visit(i); + } + // 在 tableTracer 第二行(索引 1)第 i 列写入 dfn 值 + tableTracer.patch(1, i + 1, dfn[i]); + Tracer::delay(); + tableTracer.depatch(1, i + 1); + Tracer::delay(); + + // 遍历邻接顶点 + for (int j = 0; j < (int)G.size(); ++j) { + if (G[i][j] && !visited[j]) { + // 可视化当前遍历的边 + graphTracer.visit(i, j); + Tracer::delay(); + DFSRec(G, j, i, dfn, visited, cnt, graphTracer, tableTracer, logger); + } + } +} + +// DFS函数(以顶点 i 为起点进行深度优先) +void DFS(const std::vector> &G, int start, + GraphTracer &graphTracer, Array2DTracer &tableTracer, LogTracer &logger) +{ + int n = (int)G.size(); + std::vector visited(n, false); + std::vector dfn(n, 0); + int cnt = 0; + logger.println("从顶点 " + std::to_string(start) + " 开始深度优先遍历"); + Tracer::delay(); + // 从start开始 DFS + DFSRec(G, start, -1, dfn, visited, cnt, graphTracer, tableTracer, logger); + + // 输出连通性判断 + bool connected = true; + for (int i = 0; i < n; ++i) if (!visited[i]) { connected = false; break; } + if (connected) logger.println("所有顶点都已遍历,该图连通"); + else logger.println("存在未遍历的顶点,该图不连通"); + Tracer::delay(); + + // 若图不连通,可尝试对剩余未访问顶点再调用DFS,用于其余目的(保证遍历全部连通分量) + // for (int i = 0; i < n; ++i) { + // if (!visited[i]) { + // DFSRec(G, i, -1, dfn, visited, cnt, graphTracer, tableTracer, logger); + // } + // } +} + +int main() +{ + GraphTracer graphTracer = GraphTracer("图的深度优先遍历").directed(false); + Array2DTracer tableTracer = Array2DTracer("深度优先编号"); + LogTracer logger = LogTracer("运行日志"); + Layout::setRoot(VerticalLayout({graphTracer, tableTracer, logger})); + + // 使用固定示例邻接矩阵(确定性、便于测试) + json Gjson = json::array(); + int N = 7; + for (int i = 0; i < N; ++i) { + json row = json::array(); + for (int j = 0; j < N; ++j) row.push_back(0); + Gjson.push_back(row); + } + // 添加若干边(无向) + auto addEdge = [&](int a, int b) { + Gjson[a][b] = 1; + Gjson[b][a] = 1; + }; + addEdge(1,2); addEdge(1,3); addEdge(1,4); addEdge(2,4); addEdge(2,6); + addEdge(3,4); addEdge(3,5); addEdge(4,5); addEdge(4,6); addEdge(5,6); + graphTracer.set(Gjson); + // 使用圆形布局避免节点在一条直线 + graphTracer.layoutCircle(); + + // 初始化表格:第一行为顶点编号(0..n-1),第二行为 DFN(初始为 "-") + json row0 = json::array(); + json row1 = json::array(); + row0.push_back("顶点"); + row1.push_back("深度优先编号"); + for (int i = 1; i < N+1; ++i) { + row0.push_back(std::to_string(i - 1)); + row1.push_back(std::string("-")); + } + json table = json::array(); + table.push_back(row0); + table.push_back(row1); + tableTracer.set(table); + Tracer::delay(); + + // 把邻接矩阵转成 std::vector> + std::vector> G; + for (size_t i = 0; i < Gjson.size(); ++i) { + std::vector row; + for (size_t j = 0; j < Gjson[i].size(); ++j) { + row.push_back((int)Gjson[i][j]); + } + G.push_back(row); + } + + // 进行深度优先遍历(从顶点 1 开始) + DFS(G, 1, graphTracer, tableTracer, logger); + + return 0; +} \ No newline at end of file diff --git a/Finished/DFS/DFS-Graph.exe b/Finished/DFS/DFS-Graph.exe new file mode 100755 index 0000000..d2a74f2 Binary files /dev/null and b/Finished/DFS/DFS-Graph.exe differ diff --git a/Finished/DFS/DFS-Graph.json b/Finished/DFS/DFS-Graph.json new file mode 100644 index 0000000..72a61b2 --- /dev/null +++ b/Finished/DFS/DFS-Graph.json @@ -0,0 +1 @@ +[{"args":["图的深度优先遍历"],"key":"nbf3xbn6","method":"GraphTracer"},{"args":[false],"key":"nbf3xbn6","method":"directed"},{"args":["深度优先编号"],"key":"zyted1bb","method":"Array2DTracer"},{"args":["运行日志"],"key":"0jvj46nu","method":"LogTracer"},{"args":[["nbf3xbn6","zyted1bb","0jvj46nu"]],"key":"npiw3fxr","method":"VerticalLayout"},{"args":["npiw3fxr"],"key":null,"method":"setRoot"},{"args":[[[0,0,0,0,0,0,0],[0,0,1,1,1,0,0],[0,1,0,0,1,0,1],[0,1,0,0,1,1,0],[0,1,1,1,0,1,1],[0,0,0,1,1,0,1],[0,0,1,0,1,1,0]]],"key":"nbf3xbn6","method":"set"},{"args":[],"key":"nbf3xbn6","method":"layoutCircle"},{"args":[[["顶点","0","1","2","3","4","5","6"],["深度优先编号","-","-","-","-","-","-","-"]]],"key":"zyted1bb","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["从顶点 1 开始深度优先遍历"],"key":"0jvj46nu","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"nbf3xbn6","method":"visit"},{"args":[1,2,1],"key":"zyted1bb","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"zyted1bb","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"nbf3xbn6","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"nbf3xbn6","method":"visit"},{"args":[1,3,2],"key":"zyted1bb","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"zyted1bb","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"nbf3xbn6","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[4,2],"key":"nbf3xbn6","method":"visit"},{"args":[1,5,3],"key":"zyted1bb","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"zyted1bb","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[4,3],"key":"nbf3xbn6","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[3,4],"key":"nbf3xbn6","method":"visit"},{"args":[1,4,4],"key":"zyted1bb","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"zyted1bb","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[3,5],"key":"nbf3xbn6","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[5,3],"key":"nbf3xbn6","method":"visit"},{"args":[1,6,5],"key":"zyted1bb","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"zyted1bb","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[5,6],"key":"nbf3xbn6","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[6,5],"key":"nbf3xbn6","method":"visit"},{"args":[1,7,6],"key":"zyted1bb","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"zyted1bb","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["存在未遍历的顶点,该图不连通"],"key":"0jvj46nu","method":"println"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/Finished/DFS/DFS-Tree.cpp b/Finished/DFS/DFS-Tree.cpp new file mode 100644 index 0000000..e56db69 --- /dev/null +++ b/Finished/DFS/DFS-Tree.cpp @@ -0,0 +1,130 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +// 递归实现的 DFS(与图片中的 DFS2 思路一致) +// G: 邻接矩阵(0/1),i: 当前访问顶点,parent: 父节点(-1 表示无) +// dfn: 深度优先编号数组,visited: 访问标记,cnt: 编号计数器(引用传递) +// graphTracer, tableTracer, logger 用于可视化 +void DFSRec(const std::vector> &G, int i, int parent, + std::vector &dfn, std::vector &visited, int &cnt, + GraphTracer &graphTracer, Array2DTracer &tableTracer, LogTracer &logger) +{ + // 访问顶点 i + visited[i] = true; + dfn[i] = ++cnt; + + // 可视化:标注节点(高亮访问)并在表格中填写编号 + if (parent >= 0) { + graphTracer.visit(i, parent); + } else { + graphTracer.visit(i); + } + // 在 tableTracer 第二行(索引 1)第 i+1 列写入 dfn 值(第一列为表头) + tableTracer.patch(1, i + 1, dfn[i]); + Tracer::delay(); + tableTracer.depatch(1, i + 1); + Tracer::delay(); + + // 遍历邻接顶点 + for (int j = 0; j < (int)G.size(); ++j) { + if (G[i][j] && !visited[j]) { + // 可视化当前遍历的边 + graphTracer.visit(i, j); + Tracer::delay(); + DFSRec(G, j, i, dfn, visited, cnt, graphTracer, tableTracer, logger); + } + } +} + +// 对外的 DFS 函数:按照图片的 DFS2 风格(以顶点 i 为起点进行深度优先) +void DFS(const std::vector> &G, int start, + GraphTracer &graphTracer, Array2DTracer &tableTracer, LogTracer &logger) +{ + int n = (int)G.size(); + std::vector visited(n, false); + std::vector dfn(n, 0); + int cnt = 0; + logger.println("从顶点 " + std::to_string(start) + " 开始深度优先遍历"); + Tracer::delay(); + + // 初始化表格:第一列为表头,第一行为顶点编号,第二行为 DFN(初始为 "-") + + + // 从 start 开始 DFS + DFSRec(G, start, -1, dfn, visited, cnt, graphTracer, tableTracer, logger); + // 输出连通性判断 + bool connected = true; + for (int i = 0; i < n; ++i) if (!visited[i]) { connected = false; break; } + if (connected) logger.println("所有顶点都已遍历,该图连通"); + else logger.println("存在未遍历的顶点,该图不连通"); + Tracer::delay(); + + // 若图不连通,可尝试对剩余未访问顶点再调用DFS,用于其余目的(保证遍历全部连通分量) + // for (int i = 0; i < n; ++i) { + // if (!visited[i]) { + // DFSRec(G, i, -1, dfn, visited, cnt, graphTracer, tableTracer, logger); + // } + // } + + +} + +int main() +{ + GraphTracer graphTracer = GraphTracer("二叉树的深度优先遍历").directed(false); + Array2DTracer tableTracer = Array2DTracer("深度优先编号"); + LogTracer logger = LogTracer("运行日志"); + Layout::setRoot(VerticalLayout({graphTracer, tableTracer, logger})); + + // 构造固定的二叉树示例(无向图的邻接矩阵表示) + // 使用完备二叉树的结构:对于节点 i,左孩子 2*i+1,右孩子 2*i+2(若存在) + int N = 11; // 示例:7 个节点,索引 0..6 + json Gjson = json::array(); + for (int i = 0; i < N; ++i) { + json row = json::array(); + for (int j = 0; j < N; ++j) row.push_back(0); + Gjson.push_back(row); + } + auto addEdge = [&](int a, int b){ if (a>=0 && a=0 && b> + std::vector> G; + for (size_t i = 0; i < Gjson.size(); ++i) { + std::vector row; + for (size_t j = 0; j < Gjson[i].size(); ++j) row.push_back((int)Gjson[i][j]); + G.push_back(row); + } + + // 从树根(0)开始深度优先遍历 + DFS(G, 0, graphTracer, tableTracer, logger); + + return 0; +} diff --git a/Finished/DFS/DFS-Tree.exe b/Finished/DFS/DFS-Tree.exe new file mode 100755 index 0000000..3a67aa0 Binary files /dev/null and b/Finished/DFS/DFS-Tree.exe differ diff --git a/Finished/DFS/DFS-Tree.json b/Finished/DFS/DFS-Tree.json new file mode 100644 index 0000000..8314133 --- /dev/null +++ b/Finished/DFS/DFS-Tree.json @@ -0,0 +1 @@ +[{"args":["二叉树的深度优先遍历"],"key":"y1jao0qy","method":"GraphTracer"},{"args":[false],"key":"y1jao0qy","method":"directed"},{"args":["深度优先编号"],"key":"tp86hl2b","method":"Array2DTracer"},{"args":["运行日志"],"key":"0s657dpl","method":"LogTracer"},{"args":[["y1jao0qy","tp86hl2b","0s657dpl"]],"key":"6ym1oy85","method":"VerticalLayout"},{"args":["6ym1oy85"],"key":null,"method":"setRoot"},{"args":[[[0,1,1,0,0,0,0,0,0,0,0],[1,0,0,1,1,0,0,0,0,0,0],[1,0,0,0,0,1,1,0,0,0,0],[0,1,0,0,0,0,0,1,1,0,0],[0,1,0,0,0,0,0,0,0,1,1],[0,0,1,0,0,0,0,0,0,0,0],[0,0,1,0,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,0,0],[0,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,1,0,0,0,0,0,0]]],"key":"y1jao0qy","method":"set"},{"args":[],"key":"y1jao0qy","method":"layoutTree"},{"args":[[["顶点","0","1","2","3","4","5","6","7","8","9","10"],["深度优先编号","-","-","-","-","-","-","-","-","-","-","-"]]],"key":"tp86hl2b","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["从顶点 0 开始深度优先遍历"],"key":"0s657dpl","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"y1jao0qy","method":"visit"},{"args":[1,1,1],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"y1jao0qy","method":"visit"},{"args":[1,2,2],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[3,1],"key":"y1jao0qy","method":"visit"},{"args":[1,4,3],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[7,3],"key":"y1jao0qy","method":"visit"},{"args":[1,8,4],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,8],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[3,8],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[8,3],"key":"y1jao0qy","method":"visit"},{"args":[1,9,5],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,9],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[4,1],"key":"y1jao0qy","method":"visit"},{"args":[1,5,6],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[4,9],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[9,4],"key":"y1jao0qy","method":"visit"},{"args":[1,10,7],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,10],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[4,10],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[10,4],"key":"y1jao0qy","method":"visit"},{"args":[1,11,8],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,11],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[2,0],"key":"y1jao0qy","method":"visit"},{"args":[1,3,9],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[5,2],"key":"y1jao0qy","method":"visit"},{"args":[1,6,10],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"y1jao0qy","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[6,2],"key":"y1jao0qy","method":"visit"},{"args":[1,7,11],"key":"tp86hl2b","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"tp86hl2b","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["所有顶点都已遍历,该图连通"],"key":"0s657dpl","method":"println"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/Finished/HeapOperations/Heap-DeleteMax.cpp b/Finished/HeapOperations/Heap-DeleteMax.cpp new file mode 100644 index 0000000..aa79c05 --- /dev/null +++ b/Finished/HeapOperations/Heap-DeleteMax.cpp @@ -0,0 +1,187 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +struct HEAP +{ + std::vector data; // 1-based: data[0] unused + int n; + int capacity; + HEAP(int cap = 32) : data(cap + 1, 0), n(0), capacity(cap) {} +}; + +typedef int ElemType; + +Array1DTracer heapTracer = Array1DTracer("堆的数组形式"); +LogTracer logger = LogTracer("运行日志"); +GraphTracer heapGraph = GraphTracer("最大堆").directed(false); +bool HeapFull(HEAP &heap) +{ + return (heap.n == heap.capacity); +} + +// 更新图形化的堆树视图(binary heap visual) +// 根据数组构建完全二叉树:对第 i 个节点(0-based),左孩子为 2*i+1,右孩子为 2*i+2 +void updateHeapGraph(HEAP &heap) +{ + int n = heap.n; + GraphTracer heapGraph_new = GraphTracer("最大堆").directed(false); + heapGraph = heapGraph_new; + Layout::setRoot(VerticalLayout({heapGraph, heapTracer, logger})); + // 添加节点:使用连续的数值 id (0..n-1),并把堆值作为 weight 显示 + for (int i = 0; i < n; ++i) + { + int left = 2 * i + 1; + int right = 2 * i + 2; + heapGraph.addNode(heap.data[i]); + if (left < n) + { + heapGraph.addEdge(heap.data[i], heap.data[left]); + heapGraph.addEdge(heap.data[left], heap.data[i]); + } + if (right < n) + { + heapGraph.addEdge(heap.data[i], heap.data[right]); + heapGraph.addEdge(heap.data[right], heap.data[i]); + } + } + heapGraph.layoutTree(heap.data[0]); +} + +void DeleteMax(HEAP &heap) +{ + if (heap.n == 0) + { + logger.println("堆为空,无法删除元素"); + Tracer::delay(); + return; + } + int maxElem = heap.data[0]; + logger.println("删除最大元素: " + std::to_string(maxElem) + ",并替换堆顶元素"); + heapTracer.select(0); + heapGraph.select(heap.data[0]); + heapGraph.select(heap.data[heap.n-1]); + Tracer::delay(); + + heap.data[0] = heap.data[heap.n - 1]; + heap.n--; + heapTracer.deselect(0); + heapTracer.patch(0, heap.data[0]); + heapTracer.patch(heap.n, "-"); + updateHeapGraph(heap); + heapGraph.select(heap.data[0]); + Tracer::delay(); + heapTracer.depatch(0); + heapTracer.depatch(heap.n); + heapGraph.deselect(heap.data[0]); + Tracer::delay(); + logger.println("堆顶元素被最后一个元素替换,开始下滤过程"); + Tracer::delay(); + // 下滤过程 + int i = 0; + while (true) + { + int left = 2 * i + 1; + int right = 2 * i + 2; + int largest = i; + // 找到最大子结点 + if (left < heap.n && heap.data[left] > heap.data[largest]) + largest = left; + if (right < heap.n && heap.data[right] > heap.data[largest]) + largest = right; + + if (largest != i) + { + // 可视化 + logger.println("交换元素 " + std::to_string(heap.data[i]) + " 和 " + std::to_string(heap.data[largest])); + heapGraph.select(heap.data[largest]); + heapGraph.select(heap.data[i]); + heapTracer.select(i); + heapTracer.select(largest); + Tracer::delay(); + + std::swap(heap.data[i], heap.data[largest]); + // 可视化 + heapTracer.patch(i, heap.data[i]); + heapTracer.patch(largest, heap.data[largest]); + heapTracer.deselect(i); + heapTracer.deselect(largest); + updateHeapGraph(heap); + heapGraph.select(heap.data[largest]); + heapGraph.select(heap.data[i]); + Tracer::delay(); + heapTracer.depatch(i); + heapTracer.depatch(largest); + heapGraph.deselect(heap.data[largest]); + heapGraph.deselect(heap.data[i]); + Tracer::delay(); + + i = largest; + } + else + { + break; + } + } + updateHeapGraph(heap); + logger.println("删除完成,目前堆中元素个数:" + std::to_string(heap.n)); + Tracer::delay(); +} + +int main() +{ + Layout::setRoot(VerticalLayout({heapGraph, heapTracer, logger})); + + // 创建一个示例堆(max-heap) + HEAP heap(10); + // 初始元素:索引从0开始 + std::vector init = {95, 87, 53, 45, 78, 9, 31, 17}; + // 初始化堆内容 + heap.n = (int)init.size(); + for (int i = 0; i < heap.n; ++i) + heap.data[i] = init[i]; + + // 可视化初始堆数组 + json arr = json::array(); + for (int i = 0; i < heap.capacity; ++i) + { + if (i < heap.n) + arr.push_back(heap.data[i]); + else + arr.push_back(std::string("-")); + } + heapTracer.set(arr); + + for (int i = 0; i < heap.n; ++i) + { + heapGraph.addNode(heap.data[i]); + } + for (int i = 0; i < heap.n; ++i) + { + int left = 2 * i + 1; + int right = 2 * i + 2; + if (left < heap.n) + { + heapGraph.addEdge(heap.data[i], heap.data[left]); + heapGraph.addEdge(heap.data[left], heap.data[i]); + } + if (right < heap.n) + { + heapGraph.addEdge(heap.data[i], heap.data[right]); + heapGraph.addEdge(heap.data[right], heap.data[i]); + } + } + heapGraph.layoutTree(heap.data[0]); + Tracer::delay(); + logger.println("试图删除最大元素"); + Tracer::delay(); + DeleteMax(heap); + logger.println("试图删除最大元素"); + Tracer::delay(); + DeleteMax(heap); + + return 0; +} diff --git a/Finished/HeapOperations/Heap-DeleteMax.exe b/Finished/HeapOperations/Heap-DeleteMax.exe new file mode 100755 index 0000000..a714069 Binary files /dev/null and b/Finished/HeapOperations/Heap-DeleteMax.exe differ diff --git a/Finished/HeapOperations/Heap-DeleteMax.json b/Finished/HeapOperations/Heap-DeleteMax.json new file mode 100644 index 0000000..1049d88 --- /dev/null +++ b/Finished/HeapOperations/Heap-DeleteMax.json @@ -0,0 +1 @@ +[{"args":["堆的数组形式"],"key":"04weu3om","method":"Array1DTracer"},{"args":["运行日志"],"key":"7178i47t","method":"LogTracer"},{"args":["最大堆"],"key":"p8usy3tw","method":"GraphTracer"},{"args":[false],"key":"p8usy3tw","method":"directed"},{"args":[["p8usy3tw","04weu3om","7178i47t"]],"key":"hg8fue1v","method":"VerticalLayout"},{"args":["hg8fue1v"],"key":null,"method":"setRoot"},{"args":[[95,87,53,45,78,9,31,17,"-","-"]],"key":"04weu3om","method":"set"},{"args":[95],"key":"p8usy3tw","method":"addNode"},{"args":[87],"key":"p8usy3tw","method":"addNode"},{"args":[53],"key":"p8usy3tw","method":"addNode"},{"args":[45],"key":"p8usy3tw","method":"addNode"},{"args":[78],"key":"p8usy3tw","method":"addNode"},{"args":[9],"key":"p8usy3tw","method":"addNode"},{"args":[31],"key":"p8usy3tw","method":"addNode"},{"args":[17],"key":"p8usy3tw","method":"addNode"},{"args":[95,87],"key":"p8usy3tw","method":"addEdge"},{"args":[87,95],"key":"p8usy3tw","method":"addEdge"},{"args":[95,53],"key":"p8usy3tw","method":"addEdge"},{"args":[53,95],"key":"p8usy3tw","method":"addEdge"},{"args":[87,45],"key":"p8usy3tw","method":"addEdge"},{"args":[45,87],"key":"p8usy3tw","method":"addEdge"},{"args":[87,78],"key":"p8usy3tw","method":"addEdge"},{"args":[78,87],"key":"p8usy3tw","method":"addEdge"},{"args":[53,9],"key":"p8usy3tw","method":"addEdge"},{"args":[9,53],"key":"p8usy3tw","method":"addEdge"},{"args":[53,31],"key":"p8usy3tw","method":"addEdge"},{"args":[31,53],"key":"p8usy3tw","method":"addEdge"},{"args":[45,17],"key":"p8usy3tw","method":"addEdge"},{"args":[17,45],"key":"p8usy3tw","method":"addEdge"},{"args":[95],"key":"p8usy3tw","method":"layoutTree"},{"args":[],"key":null,"method":"delay"},{"args":["试图删除最大元素"],"key":"7178i47t","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["删除最大元素: 95,并替换堆顶元素"],"key":"7178i47t","method":"println"},{"args":[0],"key":"04weu3om","method":"select"},{"args":[95],"key":"p8usy3tw","method":"select"},{"args":[17],"key":"p8usy3tw","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"04weu3om","method":"deselect"},{"args":[0,17],"key":"04weu3om","method":"patch"},{"args":[7,"-"],"key":"04weu3om","method":"patch"},{"args":["最大堆"],"key":"7js6r46h","method":"GraphTracer"},{"args":[false],"key":"7js6r46h","method":"directed"},{"args":[["7js6r46h","04weu3om","7178i47t"]],"key":"ee7jtpv9","method":"VerticalLayout"},{"args":["ee7jtpv9"],"key":null,"method":"setRoot"},{"args":[17],"key":"7js6r46h","method":"addNode"},{"args":[17,87],"key":"7js6r46h","method":"addEdge"},{"args":[87,17],"key":"7js6r46h","method":"addEdge"},{"args":[17,53],"key":"7js6r46h","method":"addEdge"},{"args":[53,17],"key":"7js6r46h","method":"addEdge"},{"args":[87],"key":"7js6r46h","method":"addNode"},{"args":[87,45],"key":"7js6r46h","method":"addEdge"},{"args":[45,87],"key":"7js6r46h","method":"addEdge"},{"args":[87,78],"key":"7js6r46h","method":"addEdge"},{"args":[78,87],"key":"7js6r46h","method":"addEdge"},{"args":[53],"key":"7js6r46h","method":"addNode"},{"args":[53,9],"key":"7js6r46h","method":"addEdge"},{"args":[9,53],"key":"7js6r46h","method":"addEdge"},{"args":[53,31],"key":"7js6r46h","method":"addEdge"},{"args":[31,53],"key":"7js6r46h","method":"addEdge"},{"args":[45],"key":"7js6r46h","method":"addNode"},{"args":[78],"key":"7js6r46h","method":"addNode"},{"args":[9],"key":"7js6r46h","method":"addNode"},{"args":[31],"key":"7js6r46h","method":"addNode"},{"args":[17],"key":"7js6r46h","method":"layoutTree"},{"args":[17],"key":"7js6r46h","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"04weu3om","method":"depatch"},{"args":[7],"key":"04weu3om","method":"depatch"},{"args":[17],"key":"7js6r46h","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["堆顶元素被最后一个元素替换,开始下滤过程"],"key":"7178i47t","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["交换元素 17 和 87"],"key":"7178i47t","method":"println"},{"args":[87],"key":"7js6r46h","method":"select"},{"args":[17],"key":"7js6r46h","method":"select"},{"args":[0],"key":"04weu3om","method":"select"},{"args":[1],"key":"04weu3om","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,87],"key":"04weu3om","method":"patch"},{"args":[1,17],"key":"04weu3om","method":"patch"},{"args":[0],"key":"04weu3om","method":"deselect"},{"args":[1],"key":"04weu3om","method":"deselect"},{"args":["最大堆"],"key":"o8sqp7qv","method":"GraphTracer"},{"args":[false],"key":"o8sqp7qv","method":"directed"},{"args":[["o8sqp7qv","04weu3om","7178i47t"]],"key":"70sox7st","method":"VerticalLayout"},{"args":["70sox7st"],"key":null,"method":"setRoot"},{"args":[87],"key":"o8sqp7qv","method":"addNode"},{"args":[87,17],"key":"o8sqp7qv","method":"addEdge"},{"args":[17,87],"key":"o8sqp7qv","method":"addEdge"},{"args":[87,53],"key":"o8sqp7qv","method":"addEdge"},{"args":[53,87],"key":"o8sqp7qv","method":"addEdge"},{"args":[17],"key":"o8sqp7qv","method":"addNode"},{"args":[17,45],"key":"o8sqp7qv","method":"addEdge"},{"args":[45,17],"key":"o8sqp7qv","method":"addEdge"},{"args":[17,78],"key":"o8sqp7qv","method":"addEdge"},{"args":[78,17],"key":"o8sqp7qv","method":"addEdge"},{"args":[53],"key":"o8sqp7qv","method":"addNode"},{"args":[53,9],"key":"o8sqp7qv","method":"addEdge"},{"args":[9,53],"key":"o8sqp7qv","method":"addEdge"},{"args":[53,31],"key":"o8sqp7qv","method":"addEdge"},{"args":[31,53],"key":"o8sqp7qv","method":"addEdge"},{"args":[45],"key":"o8sqp7qv","method":"addNode"},{"args":[78],"key":"o8sqp7qv","method":"addNode"},{"args":[9],"key":"o8sqp7qv","method":"addNode"},{"args":[31],"key":"o8sqp7qv","method":"addNode"},{"args":[87],"key":"o8sqp7qv","method":"layoutTree"},{"args":[17],"key":"o8sqp7qv","method":"select"},{"args":[87],"key":"o8sqp7qv","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"04weu3om","method":"depatch"},{"args":[1],"key":"04weu3om","method":"depatch"},{"args":[17],"key":"o8sqp7qv","method":"deselect"},{"args":[87],"key":"o8sqp7qv","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["交换元素 17 和 78"],"key":"7178i47t","method":"println"},{"args":[78],"key":"o8sqp7qv","method":"select"},{"args":[17],"key":"o8sqp7qv","method":"select"},{"args":[1],"key":"04weu3om","method":"select"},{"args":[4],"key":"04weu3om","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,78],"key":"04weu3om","method":"patch"},{"args":[4,17],"key":"04weu3om","method":"patch"},{"args":[1],"key":"04weu3om","method":"deselect"},{"args":[4],"key":"04weu3om","method":"deselect"},{"args":["最大堆"],"key":"f4m3yh5y","method":"GraphTracer"},{"args":[false],"key":"f4m3yh5y","method":"directed"},{"args":[["f4m3yh5y","04weu3om","7178i47t"]],"key":"en3azs1l","method":"VerticalLayout"},{"args":["en3azs1l"],"key":null,"method":"setRoot"},{"args":[87],"key":"f4m3yh5y","method":"addNode"},{"args":[87,78],"key":"f4m3yh5y","method":"addEdge"},{"args":[78,87],"key":"f4m3yh5y","method":"addEdge"},{"args":[87,53],"key":"f4m3yh5y","method":"addEdge"},{"args":[53,87],"key":"f4m3yh5y","method":"addEdge"},{"args":[78],"key":"f4m3yh5y","method":"addNode"},{"args":[78,45],"key":"f4m3yh5y","method":"addEdge"},{"args":[45,78],"key":"f4m3yh5y","method":"addEdge"},{"args":[78,17],"key":"f4m3yh5y","method":"addEdge"},{"args":[17,78],"key":"f4m3yh5y","method":"addEdge"},{"args":[53],"key":"f4m3yh5y","method":"addNode"},{"args":[53,9],"key":"f4m3yh5y","method":"addEdge"},{"args":[9,53],"key":"f4m3yh5y","method":"addEdge"},{"args":[53,31],"key":"f4m3yh5y","method":"addEdge"},{"args":[31,53],"key":"f4m3yh5y","method":"addEdge"},{"args":[45],"key":"f4m3yh5y","method":"addNode"},{"args":[17],"key":"f4m3yh5y","method":"addNode"},{"args":[9],"key":"f4m3yh5y","method":"addNode"},{"args":[31],"key":"f4m3yh5y","method":"addNode"},{"args":[87],"key":"f4m3yh5y","method":"layoutTree"},{"args":[17],"key":"f4m3yh5y","method":"select"},{"args":[78],"key":"f4m3yh5y","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"04weu3om","method":"depatch"},{"args":[4],"key":"04weu3om","method":"depatch"},{"args":[17],"key":"f4m3yh5y","method":"deselect"},{"args":[78],"key":"f4m3yh5y","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["最大堆"],"key":"4m3a0odf","method":"GraphTracer"},{"args":[false],"key":"4m3a0odf","method":"directed"},{"args":[["4m3a0odf","04weu3om","7178i47t"]],"key":"6ophf9wp","method":"VerticalLayout"},{"args":["6ophf9wp"],"key":null,"method":"setRoot"},{"args":[87],"key":"4m3a0odf","method":"addNode"},{"args":[87,78],"key":"4m3a0odf","method":"addEdge"},{"args":[78,87],"key":"4m3a0odf","method":"addEdge"},{"args":[87,53],"key":"4m3a0odf","method":"addEdge"},{"args":[53,87],"key":"4m3a0odf","method":"addEdge"},{"args":[78],"key":"4m3a0odf","method":"addNode"},{"args":[78,45],"key":"4m3a0odf","method":"addEdge"},{"args":[45,78],"key":"4m3a0odf","method":"addEdge"},{"args":[78,17],"key":"4m3a0odf","method":"addEdge"},{"args":[17,78],"key":"4m3a0odf","method":"addEdge"},{"args":[53],"key":"4m3a0odf","method":"addNode"},{"args":[53,9],"key":"4m3a0odf","method":"addEdge"},{"args":[9,53],"key":"4m3a0odf","method":"addEdge"},{"args":[53,31],"key":"4m3a0odf","method":"addEdge"},{"args":[31,53],"key":"4m3a0odf","method":"addEdge"},{"args":[45],"key":"4m3a0odf","method":"addNode"},{"args":[17],"key":"4m3a0odf","method":"addNode"},{"args":[9],"key":"4m3a0odf","method":"addNode"},{"args":[31],"key":"4m3a0odf","method":"addNode"},{"args":[87],"key":"4m3a0odf","method":"layoutTree"},{"args":["删除完成,目前堆中元素个数:7"],"key":"7178i47t","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["试图删除最大元素"],"key":"7178i47t","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["删除最大元素: 87,并替换堆顶元素"],"key":"7178i47t","method":"println"},{"args":[0],"key":"04weu3om","method":"select"},{"args":[87],"key":"4m3a0odf","method":"select"},{"args":[31],"key":"4m3a0odf","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"04weu3om","method":"deselect"},{"args":[0,31],"key":"04weu3om","method":"patch"},{"args":[6,"-"],"key":"04weu3om","method":"patch"},{"args":["最大堆"],"key":"va43c9qv","method":"GraphTracer"},{"args":[false],"key":"va43c9qv","method":"directed"},{"args":[["va43c9qv","04weu3om","7178i47t"]],"key":"tqheykit","method":"VerticalLayout"},{"args":["tqheykit"],"key":null,"method":"setRoot"},{"args":[31],"key":"va43c9qv","method":"addNode"},{"args":[31,78],"key":"va43c9qv","method":"addEdge"},{"args":[78,31],"key":"va43c9qv","method":"addEdge"},{"args":[31,53],"key":"va43c9qv","method":"addEdge"},{"args":[53,31],"key":"va43c9qv","method":"addEdge"},{"args":[78],"key":"va43c9qv","method":"addNode"},{"args":[78,45],"key":"va43c9qv","method":"addEdge"},{"args":[45,78],"key":"va43c9qv","method":"addEdge"},{"args":[78,17],"key":"va43c9qv","method":"addEdge"},{"args":[17,78],"key":"va43c9qv","method":"addEdge"},{"args":[53],"key":"va43c9qv","method":"addNode"},{"args":[53,9],"key":"va43c9qv","method":"addEdge"},{"args":[9,53],"key":"va43c9qv","method":"addEdge"},{"args":[45],"key":"va43c9qv","method":"addNode"},{"args":[17],"key":"va43c9qv","method":"addNode"},{"args":[9],"key":"va43c9qv","method":"addNode"},{"args":[31],"key":"va43c9qv","method":"layoutTree"},{"args":[31],"key":"va43c9qv","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"04weu3om","method":"depatch"},{"args":[6],"key":"04weu3om","method":"depatch"},{"args":[31],"key":"va43c9qv","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["堆顶元素被最后一个元素替换,开始下滤过程"],"key":"7178i47t","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["交换元素 31 和 78"],"key":"7178i47t","method":"println"},{"args":[78],"key":"va43c9qv","method":"select"},{"args":[31],"key":"va43c9qv","method":"select"},{"args":[0],"key":"04weu3om","method":"select"},{"args":[1],"key":"04weu3om","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,78],"key":"04weu3om","method":"patch"},{"args":[1,31],"key":"04weu3om","method":"patch"},{"args":[0],"key":"04weu3om","method":"deselect"},{"args":[1],"key":"04weu3om","method":"deselect"},{"args":["最大堆"],"key":"h4epf4y4","method":"GraphTracer"},{"args":[false],"key":"h4epf4y4","method":"directed"},{"args":[["h4epf4y4","04weu3om","7178i47t"]],"key":"bsz7c73k","method":"VerticalLayout"},{"args":["bsz7c73k"],"key":null,"method":"setRoot"},{"args":[78],"key":"h4epf4y4","method":"addNode"},{"args":[78,31],"key":"h4epf4y4","method":"addEdge"},{"args":[31,78],"key":"h4epf4y4","method":"addEdge"},{"args":[78,53],"key":"h4epf4y4","method":"addEdge"},{"args":[53,78],"key":"h4epf4y4","method":"addEdge"},{"args":[31],"key":"h4epf4y4","method":"addNode"},{"args":[31,45],"key":"h4epf4y4","method":"addEdge"},{"args":[45,31],"key":"h4epf4y4","method":"addEdge"},{"args":[31,17],"key":"h4epf4y4","method":"addEdge"},{"args":[17,31],"key":"h4epf4y4","method":"addEdge"},{"args":[53],"key":"h4epf4y4","method":"addNode"},{"args":[53,9],"key":"h4epf4y4","method":"addEdge"},{"args":[9,53],"key":"h4epf4y4","method":"addEdge"},{"args":[45],"key":"h4epf4y4","method":"addNode"},{"args":[17],"key":"h4epf4y4","method":"addNode"},{"args":[9],"key":"h4epf4y4","method":"addNode"},{"args":[78],"key":"h4epf4y4","method":"layoutTree"},{"args":[31],"key":"h4epf4y4","method":"select"},{"args":[78],"key":"h4epf4y4","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"04weu3om","method":"depatch"},{"args":[1],"key":"04weu3om","method":"depatch"},{"args":[31],"key":"h4epf4y4","method":"deselect"},{"args":[78],"key":"h4epf4y4","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["交换元素 31 和 45"],"key":"7178i47t","method":"println"},{"args":[45],"key":"h4epf4y4","method":"select"},{"args":[31],"key":"h4epf4y4","method":"select"},{"args":[1],"key":"04weu3om","method":"select"},{"args":[3],"key":"04weu3om","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,45],"key":"04weu3om","method":"patch"},{"args":[3,31],"key":"04weu3om","method":"patch"},{"args":[1],"key":"04weu3om","method":"deselect"},{"args":[3],"key":"04weu3om","method":"deselect"},{"args":["最大堆"],"key":"0arvekw5","method":"GraphTracer"},{"args":[false],"key":"0arvekw5","method":"directed"},{"args":[["0arvekw5","04weu3om","7178i47t"]],"key":"dba2j1hs","method":"VerticalLayout"},{"args":["dba2j1hs"],"key":null,"method":"setRoot"},{"args":[78],"key":"0arvekw5","method":"addNode"},{"args":[78,45],"key":"0arvekw5","method":"addEdge"},{"args":[45,78],"key":"0arvekw5","method":"addEdge"},{"args":[78,53],"key":"0arvekw5","method":"addEdge"},{"args":[53,78],"key":"0arvekw5","method":"addEdge"},{"args":[45],"key":"0arvekw5","method":"addNode"},{"args":[45,31],"key":"0arvekw5","method":"addEdge"},{"args":[31,45],"key":"0arvekw5","method":"addEdge"},{"args":[45,17],"key":"0arvekw5","method":"addEdge"},{"args":[17,45],"key":"0arvekw5","method":"addEdge"},{"args":[53],"key":"0arvekw5","method":"addNode"},{"args":[53,9],"key":"0arvekw5","method":"addEdge"},{"args":[9,53],"key":"0arvekw5","method":"addEdge"},{"args":[31],"key":"0arvekw5","method":"addNode"},{"args":[17],"key":"0arvekw5","method":"addNode"},{"args":[9],"key":"0arvekw5","method":"addNode"},{"args":[78],"key":"0arvekw5","method":"layoutTree"},{"args":[31],"key":"0arvekw5","method":"select"},{"args":[45],"key":"0arvekw5","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"04weu3om","method":"depatch"},{"args":[3],"key":"04weu3om","method":"depatch"},{"args":[31],"key":"0arvekw5","method":"deselect"},{"args":[45],"key":"0arvekw5","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["最大堆"],"key":"nmvbl6uy","method":"GraphTracer"},{"args":[false],"key":"nmvbl6uy","method":"directed"},{"args":[["nmvbl6uy","04weu3om","7178i47t"]],"key":"sl3x54ur","method":"VerticalLayout"},{"args":["sl3x54ur"],"key":null,"method":"setRoot"},{"args":[78],"key":"nmvbl6uy","method":"addNode"},{"args":[78,45],"key":"nmvbl6uy","method":"addEdge"},{"args":[45,78],"key":"nmvbl6uy","method":"addEdge"},{"args":[78,53],"key":"nmvbl6uy","method":"addEdge"},{"args":[53,78],"key":"nmvbl6uy","method":"addEdge"},{"args":[45],"key":"nmvbl6uy","method":"addNode"},{"args":[45,31],"key":"nmvbl6uy","method":"addEdge"},{"args":[31,45],"key":"nmvbl6uy","method":"addEdge"},{"args":[45,17],"key":"nmvbl6uy","method":"addEdge"},{"args":[17,45],"key":"nmvbl6uy","method":"addEdge"},{"args":[53],"key":"nmvbl6uy","method":"addNode"},{"args":[53,9],"key":"nmvbl6uy","method":"addEdge"},{"args":[9,53],"key":"nmvbl6uy","method":"addEdge"},{"args":[31],"key":"nmvbl6uy","method":"addNode"},{"args":[17],"key":"nmvbl6uy","method":"addNode"},{"args":[9],"key":"nmvbl6uy","method":"addNode"},{"args":[78],"key":"nmvbl6uy","method":"layoutTree"},{"args":["删除完成,目前堆中元素个数:6"],"key":"7178i47t","method":"println"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/Finished/HeapOperations/Heap-Insert.cpp b/Finished/HeapOperations/Heap-Insert.cpp new file mode 100644 index 0000000..0b01845 --- /dev/null +++ b/Finished/HeapOperations/Heap-Insert.cpp @@ -0,0 +1,191 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +struct HEAP +{ + std::vector data; // 1-based: data[0] unused + int n; + int capacity; + HEAP(int cap = 32) : data(cap + 1, 0), n(0), capacity(cap) {} +}; + +typedef int ElemType; + +Array1DTracer heapTracer = Array1DTracer("堆的数组形式"); +LogTracer logger = LogTracer("运行日志"); +GraphTracer heapGraph = GraphTracer("最大堆").directed(false); +bool HeapFull(HEAP &heap) +{ + return (heap.n == heap.capacity); +} + +// 更新图形化的堆树视图(binary heap visual) +// 根据数组构建完全二叉树:对第 i 个节点(0-based),左孩子为 2*i+1,右孩子为 2*i+2 +void updateHeapGraph(HEAP &heap) +{ + int n = heap.n; + GraphTracer heapGraph_new = GraphTracer("最大堆").directed(false); + heapGraph = heapGraph_new; + Layout::setRoot(VerticalLayout({heapGraph, heapTracer, logger})); + // 添加节点:使用连续的数值 id (0..n-1),并把堆值作为 weight 显示 + for (int i = 0; i < n; ++i) + { + int left = 2 * i + 1; + int right = 2 * i + 2; + heapGraph.addNode(heap.data[i]); + if (left < n) + { + heapGraph.addEdge(heap.data[i], heap.data[left]); + heapGraph.addEdge(heap.data[left], heap.data[i]); + } + if (right < n) + { + heapGraph.addEdge(heap.data[i], heap.data[right]); + heapGraph.addEdge(heap.data[right], heap.data[i]); + } + } + heapGraph.layoutTree(heap.data[0]); +} + +void Insert(HEAP &heap, ElemType elem) +{ + int i; + + std::vector visitidx; + if (!HeapFull(heap)) + { + i = heap.n; + int parentidx = (i - 1) / 2; + heap.n++; + heapGraph.addNode(elem); + heapGraph.addEdge(heap.data[parentidx], elem); + heapGraph.addEdge(elem, heap.data[parentidx]); + heapTracer.patch(i, elem); // 先放在最后 + heapGraph.visit(elem); + Tracer::delay(); + logger.println("将元素 " + std::to_string(elem) + " 放在堆的末尾位置,开始上浮"); + Tracer::delay(); + heapGraph.leave(elem); + heapTracer.depatch(i); + heapGraph.select(heap.data[parentidx]); + heapTracer.select(parentidx); + Tracer::delay(); + heapTracer.depatch(i); + while ((i != 0) && (elem > heap.data[parentidx])) + { + logger.println("堆中元素 " + std::to_string(heap.data[parentidx]) + " 小于插入元素 " + std::to_string(elem) + ",进行下推"); + heap.data[i] = heap.data[parentidx]; // 下推 + heap.data[parentidx] = elem; // 上浮 + // 可视化:修改堆树结构 + updateHeapGraph(heap); + heapGraph.visit(elem); + heapGraph.visit(heap.data[i]); + // 可视化:修改堆数组内容 + heapTracer.patch(parentidx, elem); + heapTracer.patch(i, heap.data[i]); + heapTracer.deselect(parentidx); + Tracer::delay(); + // visitidx.push_back(i); + + heapTracer.depatch(i); + heapTracer.depatch(parentidx); + heapGraph.leave(elem); + heapGraph.leave(heap.data[i]); + Tracer::delay(); + i = parentidx; + parentidx = (parentidx - 1) / 2; + if (heap.data[parentidx] != elem) + { + heapGraph.select(heap.data[parentidx]); + heapTracer.select(parentidx); + Tracer::delay(); + } + } + + // heapTracer.patch(i, heap.data[i]); + // visitidx.push_back(i); + if (i == 0) + { + logger.println("已到达堆顶位置,元素 " + std::to_string(elem) + " 上浮完毕"); + heapTracer.deselect(0); + } + else + { + logger.println("元素 " + std::to_string(heap.data[parentidx]) + " 大于插入元素 " + std::to_string(elem) + ",元素上浮完毕"); + heapTracer.deselect(parentidx); + heapGraph.deselect(heap.data[parentidx]); + // heapGraph.visit(heap.data[parentidx]); + } + Tracer::delay(); + + logger.println("成功插入元素 " + std::to_string(elem) + ",目前堆中元素个数:" + std::to_string(heap.n)); + Tracer::delay(); + return; + } + logger.println("堆已满, 无法插入元素: " + std::to_string(elem)); + Tracer::delay(); + std::cout << "堆已满, 无法插入元素: " << elem << std::endl; +} + +int main() +{ + Layout::setRoot(VerticalLayout({heapGraph, heapTracer, logger})); + + // 创建一个示例堆(max-heap) + HEAP heap(10); + // 初始元素:索引从0开始 + std::vector init = {95, 87, 53, 45, 78, 9, 31, 17}; + // 初始化堆内容 + heap.n = (int)init.size(); + for (int i = 0; i < heap.n; ++i) + heap.data[i] = init[i]; + + // 可视化初始堆数组 + json arr = json::array(); + for (int i = 0; i < heap.capacity; ++i) + { + if (i < heap.n) + arr.push_back(heap.data[i]); + else + arr.push_back(std::string("-")); + } + heapTracer.set(arr); + + for (int i = 0; i < heap.n; ++i) + { + heapGraph.addNode(heap.data[i]); + } + for (int i = 0; i < heap.n; ++i) + { + int left = 2 * i + 1; + int right = 2 * i + 2; + if (left < heap.n) + { + heapGraph.addEdge(heap.data[i], heap.data[left]); + heapGraph.addEdge(heap.data[left], heap.data[i]); + } + if (right < heap.n) + { + heapGraph.addEdge(heap.data[i], heap.data[right]); + heapGraph.addEdge(heap.data[right], heap.data[i]); + } + } + heapGraph.layoutTree(heap.data[0]); + Tracer::delay(); + + logger.println("试图插入元素88"); + Tracer::delay(); + Insert(heap, 88); + logger.println("试图插入元素100"); + Tracer::delay(); + Insert(heap, 100); + logger.println("试图插入元素42"); + Tracer::delay(); + Insert(heap, 42); + + return 0; +} diff --git a/Finished/HeapOperations/Heap-Insert.exe b/Finished/HeapOperations/Heap-Insert.exe new file mode 100755 index 0000000..ceafc33 Binary files /dev/null and b/Finished/HeapOperations/Heap-Insert.exe differ diff --git a/Finished/HeapOperations/Heap-Insert.json b/Finished/HeapOperations/Heap-Insert.json new file mode 100644 index 0000000..a327c7f --- /dev/null +++ b/Finished/HeapOperations/Heap-Insert.json @@ -0,0 +1 @@ +[{"args":["堆的数组形式"],"key":"hezviv6n","method":"Array1DTracer"},{"args":["运行日志"],"key":"a1zq24z9","method":"LogTracer"},{"args":["最大堆"],"key":"jiqokdmt","method":"GraphTracer"},{"args":[false],"key":"jiqokdmt","method":"directed"},{"args":[["jiqokdmt","hezviv6n","a1zq24z9"]],"key":"e0zg2xtp","method":"VerticalLayout"},{"args":["e0zg2xtp"],"key":null,"method":"setRoot"},{"args":[[95,87,53,45,78,9,31,17,"-","-"]],"key":"hezviv6n","method":"set"},{"args":[95],"key":"jiqokdmt","method":"addNode"},{"args":[87],"key":"jiqokdmt","method":"addNode"},{"args":[53],"key":"jiqokdmt","method":"addNode"},{"args":[45],"key":"jiqokdmt","method":"addNode"},{"args":[78],"key":"jiqokdmt","method":"addNode"},{"args":[9],"key":"jiqokdmt","method":"addNode"},{"args":[31],"key":"jiqokdmt","method":"addNode"},{"args":[17],"key":"jiqokdmt","method":"addNode"},{"args":[95,87],"key":"jiqokdmt","method":"addEdge"},{"args":[87,95],"key":"jiqokdmt","method":"addEdge"},{"args":[95,53],"key":"jiqokdmt","method":"addEdge"},{"args":[53,95],"key":"jiqokdmt","method":"addEdge"},{"args":[87,45],"key":"jiqokdmt","method":"addEdge"},{"args":[45,87],"key":"jiqokdmt","method":"addEdge"},{"args":[87,78],"key":"jiqokdmt","method":"addEdge"},{"args":[78,87],"key":"jiqokdmt","method":"addEdge"},{"args":[53,9],"key":"jiqokdmt","method":"addEdge"},{"args":[9,53],"key":"jiqokdmt","method":"addEdge"},{"args":[53,31],"key":"jiqokdmt","method":"addEdge"},{"args":[31,53],"key":"jiqokdmt","method":"addEdge"},{"args":[45,17],"key":"jiqokdmt","method":"addEdge"},{"args":[17,45],"key":"jiqokdmt","method":"addEdge"},{"args":[95],"key":"jiqokdmt","method":"layoutTree"},{"args":[],"key":null,"method":"delay"},{"args":["试图插入元素88"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[88],"key":"jiqokdmt","method":"addNode"},{"args":[45,88],"key":"jiqokdmt","method":"addEdge"},{"args":[88,45],"key":"jiqokdmt","method":"addEdge"},{"args":[8,88],"key":"hezviv6n","method":"patch"},{"args":[88],"key":"jiqokdmt","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["将元素 88 放在堆的末尾位置,开始上浮"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[88],"key":"jiqokdmt","method":"leave"},{"args":[8],"key":"hezviv6n","method":"depatch"},{"args":[45],"key":"jiqokdmt","method":"select"},{"args":[3],"key":"hezviv6n","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[8],"key":"hezviv6n","method":"depatch"},{"args":["堆中元素 45 小于插入元素 88,进行下推"],"key":"a1zq24z9","method":"println"},{"args":["最大堆"],"key":"6xwxahfj","method":"GraphTracer"},{"args":[false],"key":"6xwxahfj","method":"directed"},{"args":[["6xwxahfj","hezviv6n","a1zq24z9"]],"key":"069hwzcr","method":"VerticalLayout"},{"args":["069hwzcr"],"key":null,"method":"setRoot"},{"args":[95],"key":"6xwxahfj","method":"addNode"},{"args":[95,87],"key":"6xwxahfj","method":"addEdge"},{"args":[87,95],"key":"6xwxahfj","method":"addEdge"},{"args":[95,53],"key":"6xwxahfj","method":"addEdge"},{"args":[53,95],"key":"6xwxahfj","method":"addEdge"},{"args":[87],"key":"6xwxahfj","method":"addNode"},{"args":[87,88],"key":"6xwxahfj","method":"addEdge"},{"args":[88,87],"key":"6xwxahfj","method":"addEdge"},{"args":[87,78],"key":"6xwxahfj","method":"addEdge"},{"args":[78,87],"key":"6xwxahfj","method":"addEdge"},{"args":[53],"key":"6xwxahfj","method":"addNode"},{"args":[53,9],"key":"6xwxahfj","method":"addEdge"},{"args":[9,53],"key":"6xwxahfj","method":"addEdge"},{"args":[53,31],"key":"6xwxahfj","method":"addEdge"},{"args":[31,53],"key":"6xwxahfj","method":"addEdge"},{"args":[88],"key":"6xwxahfj","method":"addNode"},{"args":[88,17],"key":"6xwxahfj","method":"addEdge"},{"args":[17,88],"key":"6xwxahfj","method":"addEdge"},{"args":[88,45],"key":"6xwxahfj","method":"addEdge"},{"args":[45,88],"key":"6xwxahfj","method":"addEdge"},{"args":[78],"key":"6xwxahfj","method":"addNode"},{"args":[9],"key":"6xwxahfj","method":"addNode"},{"args":[31],"key":"6xwxahfj","method":"addNode"},{"args":[17],"key":"6xwxahfj","method":"addNode"},{"args":[45],"key":"6xwxahfj","method":"addNode"},{"args":[95],"key":"6xwxahfj","method":"layoutTree"},{"args":[88],"key":"6xwxahfj","method":"visit"},{"args":[45],"key":"6xwxahfj","method":"visit"},{"args":[3,88],"key":"hezviv6n","method":"patch"},{"args":[8,45],"key":"hezviv6n","method":"patch"},{"args":[3],"key":"hezviv6n","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[8],"key":"hezviv6n","method":"depatch"},{"args":[3],"key":"hezviv6n","method":"depatch"},{"args":[88],"key":"6xwxahfj","method":"leave"},{"args":[45],"key":"6xwxahfj","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[87],"key":"6xwxahfj","method":"select"},{"args":[1],"key":"hezviv6n","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["堆中元素 87 小于插入元素 88,进行下推"],"key":"a1zq24z9","method":"println"},{"args":["最大堆"],"key":"lk8l2vvl","method":"GraphTracer"},{"args":[false],"key":"lk8l2vvl","method":"directed"},{"args":[["lk8l2vvl","hezviv6n","a1zq24z9"]],"key":"558b2c73","method":"VerticalLayout"},{"args":["558b2c73"],"key":null,"method":"setRoot"},{"args":[95],"key":"lk8l2vvl","method":"addNode"},{"args":[95,88],"key":"lk8l2vvl","method":"addEdge"},{"args":[88,95],"key":"lk8l2vvl","method":"addEdge"},{"args":[95,53],"key":"lk8l2vvl","method":"addEdge"},{"args":[53,95],"key":"lk8l2vvl","method":"addEdge"},{"args":[88],"key":"lk8l2vvl","method":"addNode"},{"args":[88,87],"key":"lk8l2vvl","method":"addEdge"},{"args":[87,88],"key":"lk8l2vvl","method":"addEdge"},{"args":[88,78],"key":"lk8l2vvl","method":"addEdge"},{"args":[78,88],"key":"lk8l2vvl","method":"addEdge"},{"args":[53],"key":"lk8l2vvl","method":"addNode"},{"args":[53,9],"key":"lk8l2vvl","method":"addEdge"},{"args":[9,53],"key":"lk8l2vvl","method":"addEdge"},{"args":[53,31],"key":"lk8l2vvl","method":"addEdge"},{"args":[31,53],"key":"lk8l2vvl","method":"addEdge"},{"args":[87],"key":"lk8l2vvl","method":"addNode"},{"args":[87,17],"key":"lk8l2vvl","method":"addEdge"},{"args":[17,87],"key":"lk8l2vvl","method":"addEdge"},{"args":[87,45],"key":"lk8l2vvl","method":"addEdge"},{"args":[45,87],"key":"lk8l2vvl","method":"addEdge"},{"args":[78],"key":"lk8l2vvl","method":"addNode"},{"args":[9],"key":"lk8l2vvl","method":"addNode"},{"args":[31],"key":"lk8l2vvl","method":"addNode"},{"args":[17],"key":"lk8l2vvl","method":"addNode"},{"args":[45],"key":"lk8l2vvl","method":"addNode"},{"args":[95],"key":"lk8l2vvl","method":"layoutTree"},{"args":[88],"key":"lk8l2vvl","method":"visit"},{"args":[87],"key":"lk8l2vvl","method":"visit"},{"args":[1,88],"key":"hezviv6n","method":"patch"},{"args":[3,87],"key":"hezviv6n","method":"patch"},{"args":[1],"key":"hezviv6n","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"hezviv6n","method":"depatch"},{"args":[1],"key":"hezviv6n","method":"depatch"},{"args":[88],"key":"lk8l2vvl","method":"leave"},{"args":[87],"key":"lk8l2vvl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[95],"key":"lk8l2vvl","method":"select"},{"args":[0],"key":"hezviv6n","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["元素 95 大于插入元素 88,元素上浮完毕"],"key":"a1zq24z9","method":"println"},{"args":[0],"key":"hezviv6n","method":"deselect"},{"args":[95],"key":"lk8l2vvl","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["成功插入元素 88,目前堆中元素个数:9"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["试图插入元素100"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[100],"key":"lk8l2vvl","method":"addNode"},{"args":[78,100],"key":"lk8l2vvl","method":"addEdge"},{"args":[100,78],"key":"lk8l2vvl","method":"addEdge"},{"args":[9,100],"key":"hezviv6n","method":"patch"},{"args":[100],"key":"lk8l2vvl","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":["将元素 100 放在堆的末尾位置,开始上浮"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[100],"key":"lk8l2vvl","method":"leave"},{"args":[9],"key":"hezviv6n","method":"depatch"},{"args":[78],"key":"lk8l2vvl","method":"select"},{"args":[4],"key":"hezviv6n","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[9],"key":"hezviv6n","method":"depatch"},{"args":["堆中元素 78 小于插入元素 100,进行下推"],"key":"a1zq24z9","method":"println"},{"args":["最大堆"],"key":"f86olomx","method":"GraphTracer"},{"args":[false],"key":"f86olomx","method":"directed"},{"args":[["f86olomx","hezviv6n","a1zq24z9"]],"key":"5pdn10ft","method":"VerticalLayout"},{"args":["5pdn10ft"],"key":null,"method":"setRoot"},{"args":[95],"key":"f86olomx","method":"addNode"},{"args":[95,88],"key":"f86olomx","method":"addEdge"},{"args":[88,95],"key":"f86olomx","method":"addEdge"},{"args":[95,53],"key":"f86olomx","method":"addEdge"},{"args":[53,95],"key":"f86olomx","method":"addEdge"},{"args":[88],"key":"f86olomx","method":"addNode"},{"args":[88,87],"key":"f86olomx","method":"addEdge"},{"args":[87,88],"key":"f86olomx","method":"addEdge"},{"args":[88,100],"key":"f86olomx","method":"addEdge"},{"args":[100,88],"key":"f86olomx","method":"addEdge"},{"args":[53],"key":"f86olomx","method":"addNode"},{"args":[53,9],"key":"f86olomx","method":"addEdge"},{"args":[9,53],"key":"f86olomx","method":"addEdge"},{"args":[53,31],"key":"f86olomx","method":"addEdge"},{"args":[31,53],"key":"f86olomx","method":"addEdge"},{"args":[87],"key":"f86olomx","method":"addNode"},{"args":[87,17],"key":"f86olomx","method":"addEdge"},{"args":[17,87],"key":"f86olomx","method":"addEdge"},{"args":[87,45],"key":"f86olomx","method":"addEdge"},{"args":[45,87],"key":"f86olomx","method":"addEdge"},{"args":[100],"key":"f86olomx","method":"addNode"},{"args":[100,78],"key":"f86olomx","method":"addEdge"},{"args":[78,100],"key":"f86olomx","method":"addEdge"},{"args":[9],"key":"f86olomx","method":"addNode"},{"args":[31],"key":"f86olomx","method":"addNode"},{"args":[17],"key":"f86olomx","method":"addNode"},{"args":[45],"key":"f86olomx","method":"addNode"},{"args":[78],"key":"f86olomx","method":"addNode"},{"args":[95],"key":"f86olomx","method":"layoutTree"},{"args":[100],"key":"f86olomx","method":"visit"},{"args":[78],"key":"f86olomx","method":"visit"},{"args":[4,100],"key":"hezviv6n","method":"patch"},{"args":[9,78],"key":"hezviv6n","method":"patch"},{"args":[4],"key":"hezviv6n","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[9],"key":"hezviv6n","method":"depatch"},{"args":[4],"key":"hezviv6n","method":"depatch"},{"args":[100],"key":"f86olomx","method":"leave"},{"args":[78],"key":"f86olomx","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[88],"key":"f86olomx","method":"select"},{"args":[1],"key":"hezviv6n","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["堆中元素 88 小于插入元素 100,进行下推"],"key":"a1zq24z9","method":"println"},{"args":["最大堆"],"key":"zqe9g1t7","method":"GraphTracer"},{"args":[false],"key":"zqe9g1t7","method":"directed"},{"args":[["zqe9g1t7","hezviv6n","a1zq24z9"]],"key":"xmonldlf","method":"VerticalLayout"},{"args":["xmonldlf"],"key":null,"method":"setRoot"},{"args":[95],"key":"zqe9g1t7","method":"addNode"},{"args":[95,100],"key":"zqe9g1t7","method":"addEdge"},{"args":[100,95],"key":"zqe9g1t7","method":"addEdge"},{"args":[95,53],"key":"zqe9g1t7","method":"addEdge"},{"args":[53,95],"key":"zqe9g1t7","method":"addEdge"},{"args":[100],"key":"zqe9g1t7","method":"addNode"},{"args":[100,87],"key":"zqe9g1t7","method":"addEdge"},{"args":[87,100],"key":"zqe9g1t7","method":"addEdge"},{"args":[100,88],"key":"zqe9g1t7","method":"addEdge"},{"args":[88,100],"key":"zqe9g1t7","method":"addEdge"},{"args":[53],"key":"zqe9g1t7","method":"addNode"},{"args":[53,9],"key":"zqe9g1t7","method":"addEdge"},{"args":[9,53],"key":"zqe9g1t7","method":"addEdge"},{"args":[53,31],"key":"zqe9g1t7","method":"addEdge"},{"args":[31,53],"key":"zqe9g1t7","method":"addEdge"},{"args":[87],"key":"zqe9g1t7","method":"addNode"},{"args":[87,17],"key":"zqe9g1t7","method":"addEdge"},{"args":[17,87],"key":"zqe9g1t7","method":"addEdge"},{"args":[87,45],"key":"zqe9g1t7","method":"addEdge"},{"args":[45,87],"key":"zqe9g1t7","method":"addEdge"},{"args":[88],"key":"zqe9g1t7","method":"addNode"},{"args":[88,78],"key":"zqe9g1t7","method":"addEdge"},{"args":[78,88],"key":"zqe9g1t7","method":"addEdge"},{"args":[9],"key":"zqe9g1t7","method":"addNode"},{"args":[31],"key":"zqe9g1t7","method":"addNode"},{"args":[17],"key":"zqe9g1t7","method":"addNode"},{"args":[45],"key":"zqe9g1t7","method":"addNode"},{"args":[78],"key":"zqe9g1t7","method":"addNode"},{"args":[95],"key":"zqe9g1t7","method":"layoutTree"},{"args":[100],"key":"zqe9g1t7","method":"visit"},{"args":[88],"key":"zqe9g1t7","method":"visit"},{"args":[1,100],"key":"hezviv6n","method":"patch"},{"args":[4,88],"key":"hezviv6n","method":"patch"},{"args":[1],"key":"hezviv6n","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"hezviv6n","method":"depatch"},{"args":[1],"key":"hezviv6n","method":"depatch"},{"args":[100],"key":"zqe9g1t7","method":"leave"},{"args":[88],"key":"zqe9g1t7","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[95],"key":"zqe9g1t7","method":"select"},{"args":[0],"key":"hezviv6n","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["堆中元素 95 小于插入元素 100,进行下推"],"key":"a1zq24z9","method":"println"},{"args":["最大堆"],"key":"26uylffm","method":"GraphTracer"},{"args":[false],"key":"26uylffm","method":"directed"},{"args":[["26uylffm","hezviv6n","a1zq24z9"]],"key":"0rfx5x0f","method":"VerticalLayout"},{"args":["0rfx5x0f"],"key":null,"method":"setRoot"},{"args":[100],"key":"26uylffm","method":"addNode"},{"args":[100,95],"key":"26uylffm","method":"addEdge"},{"args":[95,100],"key":"26uylffm","method":"addEdge"},{"args":[100,53],"key":"26uylffm","method":"addEdge"},{"args":[53,100],"key":"26uylffm","method":"addEdge"},{"args":[95],"key":"26uylffm","method":"addNode"},{"args":[95,87],"key":"26uylffm","method":"addEdge"},{"args":[87,95],"key":"26uylffm","method":"addEdge"},{"args":[95,88],"key":"26uylffm","method":"addEdge"},{"args":[88,95],"key":"26uylffm","method":"addEdge"},{"args":[53],"key":"26uylffm","method":"addNode"},{"args":[53,9],"key":"26uylffm","method":"addEdge"},{"args":[9,53],"key":"26uylffm","method":"addEdge"},{"args":[53,31],"key":"26uylffm","method":"addEdge"},{"args":[31,53],"key":"26uylffm","method":"addEdge"},{"args":[87],"key":"26uylffm","method":"addNode"},{"args":[87,17],"key":"26uylffm","method":"addEdge"},{"args":[17,87],"key":"26uylffm","method":"addEdge"},{"args":[87,45],"key":"26uylffm","method":"addEdge"},{"args":[45,87],"key":"26uylffm","method":"addEdge"},{"args":[88],"key":"26uylffm","method":"addNode"},{"args":[88,78],"key":"26uylffm","method":"addEdge"},{"args":[78,88],"key":"26uylffm","method":"addEdge"},{"args":[9],"key":"26uylffm","method":"addNode"},{"args":[31],"key":"26uylffm","method":"addNode"},{"args":[17],"key":"26uylffm","method":"addNode"},{"args":[45],"key":"26uylffm","method":"addNode"},{"args":[78],"key":"26uylffm","method":"addNode"},{"args":[100],"key":"26uylffm","method":"layoutTree"},{"args":[100],"key":"26uylffm","method":"visit"},{"args":[95],"key":"26uylffm","method":"visit"},{"args":[0,100],"key":"hezviv6n","method":"patch"},{"args":[1,95],"key":"hezviv6n","method":"patch"},{"args":[0],"key":"hezviv6n","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"hezviv6n","method":"depatch"},{"args":[0],"key":"hezviv6n","method":"depatch"},{"args":[100],"key":"26uylffm","method":"leave"},{"args":[95],"key":"26uylffm","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":["已到达堆顶位置,元素 100 上浮完毕"],"key":"a1zq24z9","method":"println"},{"args":[0],"key":"hezviv6n","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["成功插入元素 100,目前堆中元素个数:10"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["试图插入元素42"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["堆已满, 无法插入元素: 42"],"key":"a1zq24z9","method":"println"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/Finished/KMP/KMP.cpp b/Finished/KMP/KMP.cpp new file mode 100644 index 0000000..bafc8d2 --- /dev/null +++ b/Finished/KMP/KMP.cpp @@ -0,0 +1,225 @@ +#include "algorithm-visualizer.h" +#include +#include + +using json = nlohmann::json; +Array2DTracer pattern_tracer = Array2DTracer("模式串"); +Array1DTracer string_tracer = Array1DTracer("目标串"); +LogTracer logger = LogTracer("运行日志"); + +void GetNext(char *T, int Next[]) +{ + int lenT = std::strlen(T); // lenT为模式串T的长度 + int j = 0, k = -1; + if (lenT <= 0) + return; + // 可视化 + logger.println("开始计算Next数组,初始化Next[0] = -1"); + Tracer::delay(); + Next[0] = -1; + + // 可视化 + pattern_tracer.patch(0, 1, -1); + pattern_tracer.depatch(0, 1); + Tracer::delay(); + + // 在 j < lenT 时扩展 Next,避免写出界 + while (j < lenT) + { + if (k == -1 || T[j] == T[k]) + { + // 需要向前分别跨越一个 + if (k == -1) + { + logger.println("k=-1,Next[" + std::to_string(j + 1) + "]设为0"); + } + if (k != -1) + { + logger.println("模式字符匹配,Next[" + std::to_string(j + 1) + "]设为" + std::to_string(k + 1)); + } + Tracer::delay(); + + ++j; + ++k; + Next[j] = k; + pattern_tracer.patch(0, j + 1, k); + Tracer::delay(); + pattern_tracer.depatch(0, j + 1); + pattern_tracer.deselect(1, j); + pattern_tracer.deselect(2, k); + Tracer::delay(); + if (j < lenT) + { + pattern_tracer.select(1, j + 1); + pattern_tracer.select(2, k + 1); + Tracer::delay(); + } + } + else + { + // 可视化 + logger.println(std::string("不匹配,k 从 ") + std::to_string(k) + " 回退到 Next[k] = " + std::to_string(Next[k])); + if (Next[k] != -1) + { + pattern_tracer.select(0, k + 1); + Tracer::delay(); + pattern_tracer.deselect(2, k + 1); + pattern_tracer.select(2, Next[k] + 1); + Tracer::delay(); + pattern_tracer.deselect(0, k + 1); + Tracer::delay(); + k = Next[k]; + } + else + { + logger.println("k 回退到 -1"); + Tracer::delay(); + pattern_tracer.select(0, k + 1); + Tracer::delay(); + pattern_tracer.deselect(2, k + 1); + Tracer::delay(); + pattern_tracer.deselect(0, k + 1); + Tracer::delay(); + k = Next[k]; + } + } + } + // 可视化 + pattern_tracer.deselect(2, k + 2); + json row_index = json::array(); + row_index.push_back(std::string("索引")); + for (int i = 0; i < lenT; ++i) + row_index.push_back(i); + row_index.push_back("-"); // 补齐列数 + json row_next = json::array(); + row_next.push_back(std::string("Next值字符")); + for (int i = 0; i < lenT + 1; ++i) + row_next.push_back(Next[i]); + json row_pat = json::array(); + row_pat.push_back(std::string("模式字符")); + for (int i = 0; i < lenT; ++i) + row_pat.push_back(std::string(1, T[i])); + row_pat.push_back("-"); // 补齐列数 + pattern_tracer.set(json::array({row_index, row_next, row_pat})); + Tracer::delay(); +} + +int StrMatch_KMP(char *S, char *T, int pos = 0) +{ + // S 为主串, T 为模式, 长度分别为了 lenS 和 lenT; 串采用顺序存储结构 + int lenS = std::strlen(S); + int lenT = std::strlen(T); + std::vector match_positions; + + if (lenT == 0) + return pos; // 空模式视为在 pos 处匹配 + if (pos < 0) + pos = 0; + if (pos >= lenS) + return -1; + + // 可视化 + + json row_next = json::array(); + row_next.push_back(std::string("Next值字符")); + for (int i = 0; i < lenT + 1; ++i) + row_next.push_back("-"); + json row_patj = json::array(); + row_patj.push_back(std::string("模式字符j")); + for (int i = 0; i < lenT; ++i) + row_patj.push_back(std::string(1, T[i])); + row_patj.push_back("-"); // 补齐列数 + json row_patk = json::array(); + row_patk.push_back(std::string("模式字符k")); + for (int i = 0; i < lenT; ++i) + row_patk.push_back(std::string(1, T[i])); + row_patk.push_back("-"); // 补齐列数 + pattern_tracer.set(json::array({row_next, row_patj, row_patk})); + Tracer::delay(); + + // 为 Next 数组分配空间,大小为 lenT(足够放置 0..lenT-1 的 Next) + int *Next = new int[lenT + 1]; + // 计算 Next + GetNext(T, Next); + + logger.println("Next数组求解完毕,开始进行 KMP 模式匹配"); + Tracer::delay(); + int i = pos; + int j = 0; // 从第一个位置开始比较 + + string_tracer.select(i); + pattern_tracer.select(2, j + 1); + Tracer::delay(); + while (i < lenS && j < lenT) + { + if (j == 0 || S[i] == T[j]) + { + ++i; + ++j; + // 可视化 + if (j == 1) + logger.println("j=0, 将模式串和主串分别前移一位"); + else + logger.println(std::string("字符匹配,i 和 j 分别移动到 ") + std::to_string(i) + ", " + std::to_string(j)); + Tracer::delay(); + string_tracer.deselect(i - 1); + pattern_tracer.deselect(2, j); + pattern_tracer.deselect(0, j); + string_tracer.select(i); + pattern_tracer.select(2, j + 1); + Tracer::delay(); + } + else + { + logger.println(std::string("字符不匹配,j 从 ") + std::to_string(j) + " 回退到 Next[j] = " + std::to_string(Next[j])); + Tracer::delay(); + pattern_tracer.deselect(0, j + 1); + pattern_tracer.select(1, j + 1); // j-1 -> column j + Tracer::delay(); + pattern_tracer.deselect(2, j + 1); + pattern_tracer.select(0, Next[j] + 1); + Tracer::delay(); + pattern_tracer.select(2, Next[j] + 1); + pattern_tracer.deselect(1, j + 1); + j = Next[j]; + } + } + + delete[] Next; + + if (j == lenT) + { + // 可视化 + logger.println("匹配成功,匹配起始下标为 " + std::to_string(i - lenT)); + pattern_tracer.deselect(2, j + 1); + string_tracer.deselect(i); + string_tracer.select(i - lenT, i - 1); + Tracer::delay(); + string_tracer.deselect(i - lenT, i - 1); + + return i - lenT; // 返回匹配的起始下标 + } + else + return -1; // 匹配不成功 +} + +int main() +{ + // 示例测试 + char S[] = "AAAABAABAAAABAAABAAAA"; // 主串 + char T[] = "AAAABAAA"; // 模式串 + // 可视化 + Layout::setRoot(VerticalLayout({pattern_tracer, string_tracer, logger})); + json srow = json::array(); + for (char c : S) + srow.push_back(std::string(1, c)); + string_tracer.set(srow); + + int pos = StrMatch_KMP(S, T, 0); + if (pos >= 0) + std::cout << "匹配成功,起始下标 = " << pos << std::endl; + else + std::cout << "匹配失败" << std::endl; + + return 0; +} diff --git a/Finished/KMP/KMP.exe b/Finished/KMP/KMP.exe new file mode 100755 index 0000000..38493a7 Binary files /dev/null and b/Finished/KMP/KMP.exe differ diff --git a/Finished/KMP/KMP.json b/Finished/KMP/KMP.json new file mode 100644 index 0000000..2f9e129 --- /dev/null +++ b/Finished/KMP/KMP.json @@ -0,0 +1 @@ +[{"args":["模式串"],"key":"n8by3cwu","method":"Array2DTracer"},{"args":["目标串"],"key":"wv86qr40","method":"Array1DTracer"},{"args":["运行日志"],"key":"63uwo6kc","method":"LogTracer"},{"args":[["n8by3cwu","wv86qr40","63uwo6kc"]],"key":"806rgcxr","method":"VerticalLayout"},{"args":["806rgcxr"],"key":null,"method":"setRoot"},{"args":[["A","A","A","A","B","A","A","B","A","A","A","A","B","A","A","A","B","A","A","A","A","\u0000"]],"key":"wv86qr40","method":"set"},{"args":[[["Next值字符","-","-","-","-","-","-","-","-","-"],["模式字符j","A","A","A","A","B","A","A","A","-"],["模式字符k","A","A","A","A","B","A","A","A","-"]]],"key":"n8by3cwu","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["开始计算Next数组,初始化Next[0] = -1"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,1,-1],"key":"n8by3cwu","method":"patch"},{"args":[0,1],"key":"n8by3cwu","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["k=-1,Next[1]设为0"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,2,0],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"n8by3cwu","method":"depatch"},{"args":[1,1],"key":"n8by3cwu","method":"deselect"},{"args":[2,0],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"n8by3cwu","method":"select"},{"args":[2,1],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["模式字符匹配,Next[2]设为1"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,3,1],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"n8by3cwu","method":"depatch"},{"args":[1,2],"key":"n8by3cwu","method":"deselect"},{"args":[2,1],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"n8by3cwu","method":"select"},{"args":[2,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["模式字符匹配,Next[3]设为2"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,4,2],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"n8by3cwu","method":"depatch"},{"args":[1,3],"key":"n8by3cwu","method":"deselect"},{"args":[2,2],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"n8by3cwu","method":"select"},{"args":[2,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["模式字符匹配,Next[4]设为3"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,5,3],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,5],"key":"n8by3cwu","method":"depatch"},{"args":[1,4],"key":"n8by3cwu","method":"deselect"},{"args":[2,3],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"n8by3cwu","method":"select"},{"args":[2,4],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 3 回退到 Next[k] = 2"],"key":"63uwo6kc","method":"println"},{"args":[0,4],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"n8by3cwu","method":"deselect"},{"args":[2,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 2 回退到 Next[k] = 1"],"key":"63uwo6kc","method":"println"},{"args":[0,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,3],"key":"n8by3cwu","method":"deselect"},{"args":[2,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 1 回退到 Next[k] = 0"],"key":"63uwo6kc","method":"println"},{"args":[0,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"n8by3cwu","method":"deselect"},{"args":[2,1],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 0 回退到 Next[k] = -1"],"key":"63uwo6kc","method":"println"},{"args":["k 回退到 -1"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["k=-1,Next[5]设为0"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,6,0],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"n8by3cwu","method":"depatch"},{"args":[1,5],"key":"n8by3cwu","method":"deselect"},{"args":[2,0],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"n8by3cwu","method":"select"},{"args":[2,1],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["模式字符匹配,Next[6]设为1"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,7,1],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,7],"key":"n8by3cwu","method":"depatch"},{"args":[1,6],"key":"n8by3cwu","method":"deselect"},{"args":[2,1],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"n8by3cwu","method":"select"},{"args":[2,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["模式字符匹配,Next[7]设为2"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,8,2],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"n8by3cwu","method":"depatch"},{"args":[1,7],"key":"n8by3cwu","method":"deselect"},{"args":[2,2],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,8],"key":"n8by3cwu","method":"select"},{"args":[2,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["模式字符匹配,Next[8]设为3"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,9,3],"key":"n8by3cwu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,9],"key":"n8by3cwu","method":"depatch"},{"args":[1,8],"key":"n8by3cwu","method":"deselect"},{"args":[2,3],"key":"n8by3cwu","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"n8by3cwu","method":"deselect"},{"args":[[["索引",0,1,2,3,4,5,6,7,"-"],["Next值字符",-1,0,1,2,3,0,1,2,3],["模式字符","A","A","A","A","B","A","A","A","-"]]],"key":"n8by3cwu","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["Next数组求解完毕,开始进行 KMP 模式匹配"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"wv86qr40","method":"select"},{"args":[2,1],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["j=0, 将模式串和主串分别前移一位"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"wv86qr40","method":"deselect"},{"args":[2,1],"key":"n8by3cwu","method":"deselect"},{"args":[0,1],"key":"n8by3cwu","method":"deselect"},{"args":[1],"key":"wv86qr40","method":"select"},{"args":[2,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 2, 2"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"wv86qr40","method":"deselect"},{"args":[2,2],"key":"n8by3cwu","method":"deselect"},{"args":[0,2],"key":"n8by3cwu","method":"deselect"},{"args":[2],"key":"wv86qr40","method":"select"},{"args":[2,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 3, 3"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"wv86qr40","method":"deselect"},{"args":[2,3],"key":"n8by3cwu","method":"deselect"},{"args":[0,3],"key":"n8by3cwu","method":"deselect"},{"args":[3],"key":"wv86qr40","method":"select"},{"args":[2,4],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 4, 4"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"wv86qr40","method":"deselect"},{"args":[2,4],"key":"n8by3cwu","method":"deselect"},{"args":[0,4],"key":"n8by3cwu","method":"deselect"},{"args":[4],"key":"wv86qr40","method":"select"},{"args":[2,5],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 5, 5"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"wv86qr40","method":"deselect"},{"args":[2,5],"key":"n8by3cwu","method":"deselect"},{"args":[0,5],"key":"n8by3cwu","method":"deselect"},{"args":[5],"key":"wv86qr40","method":"select"},{"args":[2,6],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 6, 6"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"wv86qr40","method":"deselect"},{"args":[2,6],"key":"n8by3cwu","method":"deselect"},{"args":[0,6],"key":"n8by3cwu","method":"deselect"},{"args":[6],"key":"wv86qr40","method":"select"},{"args":[2,7],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 7, 7"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"wv86qr40","method":"deselect"},{"args":[2,7],"key":"n8by3cwu","method":"deselect"},{"args":[0,7],"key":"n8by3cwu","method":"deselect"},{"args":[7],"key":"wv86qr40","method":"select"},{"args":[2,8],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符不匹配,j 从 7 回退到 Next[j] = 2"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"n8by3cwu","method":"deselect"},{"args":[1,8],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,8],"key":"n8by3cwu","method":"deselect"},{"args":[0,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,3],"key":"n8by3cwu","method":"select"},{"args":[1,8],"key":"n8by3cwu","method":"deselect"},{"args":["字符不匹配,j 从 2 回退到 Next[j] = 1"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"n8by3cwu","method":"deselect"},{"args":[1,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,3],"key":"n8by3cwu","method":"deselect"},{"args":[0,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"n8by3cwu","method":"select"},{"args":[1,3],"key":"n8by3cwu","method":"deselect"},{"args":["字符不匹配,j 从 1 回退到 Next[j] = 0"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"n8by3cwu","method":"deselect"},{"args":[1,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"n8by3cwu","method":"deselect"},{"args":[0,1],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"n8by3cwu","method":"select"},{"args":[1,2],"key":"n8by3cwu","method":"deselect"},{"args":["j=0, 将模式串和主串分别前移一位"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[7],"key":"wv86qr40","method":"deselect"},{"args":[2,1],"key":"n8by3cwu","method":"deselect"},{"args":[0,1],"key":"n8by3cwu","method":"deselect"},{"args":[8],"key":"wv86qr40","method":"select"},{"args":[2,2],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 9, 2"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[8],"key":"wv86qr40","method":"deselect"},{"args":[2,2],"key":"n8by3cwu","method":"deselect"},{"args":[0,2],"key":"n8by3cwu","method":"deselect"},{"args":[9],"key":"wv86qr40","method":"select"},{"args":[2,3],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 10, 3"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[9],"key":"wv86qr40","method":"deselect"},{"args":[2,3],"key":"n8by3cwu","method":"deselect"},{"args":[0,3],"key":"n8by3cwu","method":"deselect"},{"args":[10],"key":"wv86qr40","method":"select"},{"args":[2,4],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 11, 4"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[10],"key":"wv86qr40","method":"deselect"},{"args":[2,4],"key":"n8by3cwu","method":"deselect"},{"args":[0,4],"key":"n8by3cwu","method":"deselect"},{"args":[11],"key":"wv86qr40","method":"select"},{"args":[2,5],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符不匹配,j 从 4 回退到 Next[j] = 3"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,5],"key":"n8by3cwu","method":"deselect"},{"args":[1,5],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"n8by3cwu","method":"deselect"},{"args":[0,4],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"n8by3cwu","method":"select"},{"args":[1,5],"key":"n8by3cwu","method":"deselect"},{"args":["字符匹配,i 和 j 分别移动到 12, 4"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[11],"key":"wv86qr40","method":"deselect"},{"args":[2,4],"key":"n8by3cwu","method":"deselect"},{"args":[0,4],"key":"n8by3cwu","method":"deselect"},{"args":[12],"key":"wv86qr40","method":"select"},{"args":[2,5],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 13, 5"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[12],"key":"wv86qr40","method":"deselect"},{"args":[2,5],"key":"n8by3cwu","method":"deselect"},{"args":[0,5],"key":"n8by3cwu","method":"deselect"},{"args":[13],"key":"wv86qr40","method":"select"},{"args":[2,6],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 14, 6"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[13],"key":"wv86qr40","method":"deselect"},{"args":[2,6],"key":"n8by3cwu","method":"deselect"},{"args":[0,6],"key":"n8by3cwu","method":"deselect"},{"args":[14],"key":"wv86qr40","method":"select"},{"args":[2,7],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 15, 7"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[14],"key":"wv86qr40","method":"deselect"},{"args":[2,7],"key":"n8by3cwu","method":"deselect"},{"args":[0,7],"key":"n8by3cwu","method":"deselect"},{"args":[15],"key":"wv86qr40","method":"select"},{"args":[2,8],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["字符匹配,i 和 j 分别移动到 16, 8"],"key":"63uwo6kc","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[15],"key":"wv86qr40","method":"deselect"},{"args":[2,8],"key":"n8by3cwu","method":"deselect"},{"args":[0,8],"key":"n8by3cwu","method":"deselect"},{"args":[16],"key":"wv86qr40","method":"select"},{"args":[2,9],"key":"n8by3cwu","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配成功,匹配起始下标为 8"],"key":"63uwo6kc","method":"println"},{"args":[2,9],"key":"n8by3cwu","method":"deselect"},{"args":[16],"key":"wv86qr40","method":"deselect"},{"args":[8,15],"key":"wv86qr40","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[8,15],"key":"wv86qr40","method":"deselect"}] \ No newline at end of file diff --git a/Finished/Kruskal/Kruskal.cpp b/Finished/Kruskal/Kruskal.cpp new file mode 100644 index 0000000..a079f18 --- /dev/null +++ b/Finished/Kruskal/Kruskal.cpp @@ -0,0 +1,217 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +struct Edge +{ + int begin; + int end; + int cost; +}; + +using EdgeSet = std::vector; + +struct Vertex +{ + char data; +}; + +// 路径压缩并查集(保持原样) +int Find(int x, std::vector &parents) +{ + if (parents[x] == -1 || parents[x] == x) + return x; + return parents[x] = Find(parents[x], parents); +} + +// Kruskal with visualization (keeps original logic, only adds tracer calls) +// 增加 parentsTracer 参数用于同步展示 parents 数组 +void Kruskal_Min_Tree(EdgeSet &edges, int vexnum, int arcnum, const std::vector &vertices, + GraphTracer &tracer, LogTracer &logger, Array2DTracer &edgeTable, + Array1DTracer &parentsTracer) +{ + std::vector parents(vexnum, -1); + logger.println("初始化各结点的parent为自身"); + Tracer::delay(); + for (int i = 0; i < vexnum; ++i) { + parents[i] = i; + parentsTracer.patch(i, i); + Tracer::delay(); + parentsTracer.depatch(i); + Tracer::delay(); + } + int bnf, edf; + int taken = 0; + int total_cost = 0; + logger.println("按序遍历边表,输出最小生成树的边"); + Tracer::delay(); + + for (int i = 0; i < arcnum && taken < vexnum - 1; ++i) + { + if (i > 0) { + logger.println("寻找下一条最短边"); + Tracer::delay(); + } + // 可视化,高亮边 + tracer.visit(edges[i].begin, edges[i].end); + tracer.visit(edges[i].end, edges[i].begin); + // 可视化,高亮边表 + edgeTable.selectCol(i + 1, 0, 2); + Tracer::delay(); + // 可视化:闪烁 + tracer.leave(edges[i].begin, edges[i].end); + tracer.leave(edges[i].end, edges[i].begin); + edgeTable.deselectCol(i + 1, 0, 2); + Tracer::delay(); + + logger.println("调用Find函数获取parent信息,并进行路径压缩"); + Tracer::delay(); + + bnf = Find(edges[i].begin, parents); + edf = Find(edges[i].end, parents); + + // 每次调用 Find 或合并后,同步更新 parentsTracer 的显示 + parentsTracer.patch(edges[i].begin, bnf); + parentsTracer.patch(edges[i].end, edf); + Tracer::delay(); + parentsTracer.depatch(edges[i].begin); + parentsTracer.depatch(edges[i].end); + Tracer::delay(); + + parentsTracer.select(edges[i].begin); + parentsTracer.select(edges[i].end); + Tracer::delay(); + if (bnf != edf) + { + logger.println("两者属于不同的连通分量,合并"); + Tracer::delay(); + // 合并集合 + parents[edf] = bnf; + ++taken; + total_cost += edges[i].cost; + // 更新 parents 显示:只更新被修改的索引 edf(也可以整体更新,上面已有整体更新) + + parentsTracer.patch(edf, bnf); + Tracer::delay(); + parentsTracer.depatch(edf); + parentsTracer.deselect(edges[i].begin); + parentsTracer.deselect(edges[i].end); + Tracer::delay(); + + // 双向选中边:视觉上持久高亮并输出日志 + tracer.visit(edges[i].begin, edges[i].end); + tracer.visit(edges[i].end, edges[i].begin); + // 若该边被选中,则在表中保持高亮状态(保持列选中) + edgeTable.selectCol(i + 1, 0, 2); + logger.println(std::string("选中: (") + vertices[edges[i].begin].data + "," + vertices[edges[i].end].data + ") 权值=" + std::to_string(edges[i].cost)); + Tracer::delay(); + } + else + { + logger.println("两者属于同一连通分量"); + Tracer::delay(); + // 取消表格高亮(取消列选中) + edgeTable.deselectCol(i + 1, 0, 2); + parentsTracer.deselect(edges[i].begin); + parentsTracer.deselect(edges[i].end); + Tracer::delay(); + } + } + logger.println(std::string("Kruskal算法运行结束,生成树中边的总权值: ") + std::to_string(total_cost)); +} + +int main() +{ + // 示例测试(无向加权图,顶点用字母标识) + std::vector vertices = { + {'0'}, {'1'}, {'2'}, {'3'}, {'4'}, {'5'}, {'6'}}; + + EdgeSet edges = { + {0, 1, 7}, {0, 3, 5}, {1, 2, 8}, {1, 3, 9}, {1, 4, 7}, {2, 4, 5}, {3, 4, 15}, {3, 5, 6}, {4, 5, 8}, {4, 6, 9}, {5, 6, 11}}; + + int vexnum = static_cast(vertices.size()); + int arcnum = static_cast(edges.size()); + + // Tracers + GraphTracer tracer = GraphTracer("Kruskal算法").directed(false).weighted(); + LogTracer logger = LogTracer("运行日志"); + Array2DTracer edgeTable = Array2DTracer("边表"); + Array1DTracer parentsTracer = Array1DTracer("parents数组"); // 新增用于显示 parents 数组 + Layout::setRoot(VerticalLayout({tracer, edgeTable, parentsTracer, logger})); + + // 为可视化准备邻接矩阵(GraphTracer接受 array2d) + json Gjson = json::array(); + for (int i = 0; i < vexnum; ++i) + { + json r = json::array(); + for (int j = 0; j < vexnum; ++j) + r.push_back(0); + Gjson.push_back(r); + } + for (auto &e : edges) + { + Gjson[e.begin][e.end] = e.cost; + Gjson[e.end][e.begin] = e.cost; + } + tracer.set(Gjson); + // 使用圆形布局让点均匀分布 + tracer.layoutCircle(); + + // 先对边集进行排序(不改变原始 edges 的顺序,创建一个副本 sortedEdges) + EdgeSet sortedEdges = edges; + std::sort(sortedEdges.begin(), sortedEdges.end(), [](const Edge &a, const Edge &b) + { return a.cost < b.cost; }); + + // 用 Array2DTracer 显示边表,横向:3 行 (costs, begin, end) × arcnum 列 + // 初始化表格为 3 行 arcnum+1列,填入占位符 + json table = json::array(); + for (int row = 0; row < 3; ++row) + { + json crow = json::array(); + for (int c = 0; c < arcnum + 1; ++c) crow.push_back(std::string("-")); + table.push_back(crow); + } + table[0][0] = "cost"; + table[1][0] = "begin"; + table[2][0] = "end"; + edgeTable.set(table); + + // 初始化 parentsTracer 显示为 "-" * vexnum + json pinit = json::array(); + for (int i = 0; i < vexnum; ++i) pinit.push_back(std::string("-")); + parentsTracer.set(pinit); + Tracer::delay(); + + logger.println("遍历边集,按权值从小到大填充边表"); + Tracer::delay(); + // 按照排序后的顺序填充表格(按列填:第0行为cost,第1行为begin,第2行为end) + for (int c = 0; c < arcnum; ++c) + { + const Edge &e = sortedEdges[c]; + // 填写edgeTable + edgeTable.patch(0, c + 1, e.cost); + edgeTable.patch(1, c + 1, e.begin); + edgeTable.patch(2, c + 1, e.end); + + // 在填写时闪烁:高亮该列并在图上短暂高亮对应边 + tracer.visit(e.begin, e.end); + tracer.visit(e.end, e.begin); + edgeTable.selectCol(c + 1, 0, 2); + Tracer::delay(); + tracer.leave(e.begin, e.end); + tracer.leave(e.end, e.begin); + edgeTable.deselectCol(c + 1, 0, 2); + edgeTable.depatch(0, c + 1); + edgeTable.depatch(1, c + 1); + edgeTable.depatch(2, c + 1); + Tracer::delay(); + } + + // 现在将排序后的边传入 Kruskal 算法并在运行时高亮表格对应列 + Kruskal_Min_Tree(sortedEdges, vexnum, arcnum, vertices, tracer, logger, edgeTable, parentsTracer); + + return 0; +} diff --git a/Finished/Kruskal/Kruskal.exe b/Finished/Kruskal/Kruskal.exe new file mode 100755 index 0000000..473c05c Binary files /dev/null and b/Finished/Kruskal/Kruskal.exe differ diff --git a/Finished/Kruskal/Kruskal.json b/Finished/Kruskal/Kruskal.json new file mode 100644 index 0000000..6220eeb --- /dev/null +++ b/Finished/Kruskal/Kruskal.json @@ -0,0 +1 @@ +[{"args":["Kruskal算法"],"key":"v8tbl3af","method":"GraphTracer"},{"args":[false],"key":"v8tbl3af","method":"directed"},{"args":[],"key":"v8tbl3af","method":"weighted"},{"args":["运行日志"],"key":"s6rphlb7","method":"LogTracer"},{"args":["边表"],"key":"70xvia1h","method":"Array2DTracer"},{"args":["parents数组"],"key":"0e91x4ib","method":"Array1DTracer"},{"args":[["v8tbl3af","70xvia1h","0e91x4ib","s6rphlb7"]],"key":"6fg81qc3","method":"VerticalLayout"},{"args":["6fg81qc3"],"key":null,"method":"setRoot"},{"args":[[[0,7,0,5,0,0,0],[7,0,8,9,7,0,0],[0,8,0,0,5,0,0],[5,9,0,0,15,6,0],[0,7,5,15,0,8,9],[0,0,0,6,8,0,11],[0,0,0,0,9,11,0]]],"key":"v8tbl3af","method":"set"},{"args":[],"key":"v8tbl3af","method":"layoutCircle"},{"args":[[["cost","-","-","-","-","-","-","-","-","-","-","-"],["begin","-","-","-","-","-","-","-","-","-","-","-"],["end","-","-","-","-","-","-","-","-","-","-","-"]]],"key":"70xvia1h","method":"set"},{"args":[["-","-","-","-","-","-","-"]],"key":"0e91x4ib","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["遍历边集,按权值从小到大填充边表"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,1,5],"key":"70xvia1h","method":"patch"},{"args":[1,1,0],"key":"70xvia1h","method":"patch"},{"args":[2,1,3],"key":"70xvia1h","method":"patch"},{"args":[0,3],"key":"v8tbl3af","method":"visit"},{"args":[3,0],"key":"v8tbl3af","method":"visit"},{"args":[1,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"v8tbl3af","method":"leave"},{"args":[3,0],"key":"v8tbl3af","method":"leave"},{"args":[1,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,1],"key":"70xvia1h","method":"depatch"},{"args":[1,1],"key":"70xvia1h","method":"depatch"},{"args":[2,1],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,2,5],"key":"70xvia1h","method":"patch"},{"args":[1,2,2],"key":"70xvia1h","method":"patch"},{"args":[2,2,4],"key":"70xvia1h","method":"patch"},{"args":[2,4],"key":"v8tbl3af","method":"visit"},{"args":[4,2],"key":"v8tbl3af","method":"visit"},{"args":[2,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"v8tbl3af","method":"leave"},{"args":[4,2],"key":"v8tbl3af","method":"leave"},{"args":[2,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,2],"key":"70xvia1h","method":"depatch"},{"args":[1,2],"key":"70xvia1h","method":"depatch"},{"args":[2,2],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,3,6],"key":"70xvia1h","method":"patch"},{"args":[1,3,3],"key":"70xvia1h","method":"patch"},{"args":[2,3,5],"key":"70xvia1h","method":"patch"},{"args":[3,5],"key":"v8tbl3af","method":"visit"},{"args":[5,3],"key":"v8tbl3af","method":"visit"},{"args":[3,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[3,5],"key":"v8tbl3af","method":"leave"},{"args":[5,3],"key":"v8tbl3af","method":"leave"},{"args":[3,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,3],"key":"70xvia1h","method":"depatch"},{"args":[1,3],"key":"70xvia1h","method":"depatch"},{"args":[2,3],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,4,7],"key":"70xvia1h","method":"patch"},{"args":[1,4,0],"key":"70xvia1h","method":"patch"},{"args":[2,4,1],"key":"70xvia1h","method":"patch"},{"args":[0,1],"key":"v8tbl3af","method":"visit"},{"args":[1,0],"key":"v8tbl3af","method":"visit"},{"args":[4,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"v8tbl3af","method":"leave"},{"args":[1,0],"key":"v8tbl3af","method":"leave"},{"args":[4,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,4],"key":"70xvia1h","method":"depatch"},{"args":[1,4],"key":"70xvia1h","method":"depatch"},{"args":[2,4],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,5,7],"key":"70xvia1h","method":"patch"},{"args":[1,5,1],"key":"70xvia1h","method":"patch"},{"args":[2,5,4],"key":"70xvia1h","method":"patch"},{"args":[1,4],"key":"v8tbl3af","method":"visit"},{"args":[4,1],"key":"v8tbl3af","method":"visit"},{"args":[5,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"v8tbl3af","method":"leave"},{"args":[4,1],"key":"v8tbl3af","method":"leave"},{"args":[5,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,5],"key":"70xvia1h","method":"depatch"},{"args":[1,5],"key":"70xvia1h","method":"depatch"},{"args":[2,5],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,6,8],"key":"70xvia1h","method":"patch"},{"args":[1,6,1],"key":"70xvia1h","method":"patch"},{"args":[2,6,2],"key":"70xvia1h","method":"patch"},{"args":[1,2],"key":"v8tbl3af","method":"visit"},{"args":[2,1],"key":"v8tbl3af","method":"visit"},{"args":[6,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"v8tbl3af","method":"leave"},{"args":[2,1],"key":"v8tbl3af","method":"leave"},{"args":[6,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,6],"key":"70xvia1h","method":"depatch"},{"args":[1,6],"key":"70xvia1h","method":"depatch"},{"args":[2,6],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,7,8],"key":"70xvia1h","method":"patch"},{"args":[1,7,4],"key":"70xvia1h","method":"patch"},{"args":[2,7,5],"key":"70xvia1h","method":"patch"},{"args":[4,5],"key":"v8tbl3af","method":"visit"},{"args":[5,4],"key":"v8tbl3af","method":"visit"},{"args":[7,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[4,5],"key":"v8tbl3af","method":"leave"},{"args":[5,4],"key":"v8tbl3af","method":"leave"},{"args":[7,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,7],"key":"70xvia1h","method":"depatch"},{"args":[1,7],"key":"70xvia1h","method":"depatch"},{"args":[2,7],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,8,9],"key":"70xvia1h","method":"patch"},{"args":[1,8,1],"key":"70xvia1h","method":"patch"},{"args":[2,8,3],"key":"70xvia1h","method":"patch"},{"args":[1,3],"key":"v8tbl3af","method":"visit"},{"args":[3,1],"key":"v8tbl3af","method":"visit"},{"args":[8,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"v8tbl3af","method":"leave"},{"args":[3,1],"key":"v8tbl3af","method":"leave"},{"args":[8,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,8],"key":"70xvia1h","method":"depatch"},{"args":[1,8],"key":"70xvia1h","method":"depatch"},{"args":[2,8],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,9,9],"key":"70xvia1h","method":"patch"},{"args":[1,9,4],"key":"70xvia1h","method":"patch"},{"args":[2,9,6],"key":"70xvia1h","method":"patch"},{"args":[4,6],"key":"v8tbl3af","method":"visit"},{"args":[6,4],"key":"v8tbl3af","method":"visit"},{"args":[9,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[4,6],"key":"v8tbl3af","method":"leave"},{"args":[6,4],"key":"v8tbl3af","method":"leave"},{"args":[9,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,9],"key":"70xvia1h","method":"depatch"},{"args":[1,9],"key":"70xvia1h","method":"depatch"},{"args":[2,9],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,10,11],"key":"70xvia1h","method":"patch"},{"args":[1,10,5],"key":"70xvia1h","method":"patch"},{"args":[2,10,6],"key":"70xvia1h","method":"patch"},{"args":[5,6],"key":"v8tbl3af","method":"visit"},{"args":[6,5],"key":"v8tbl3af","method":"visit"},{"args":[10,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[5,6],"key":"v8tbl3af","method":"leave"},{"args":[6,5],"key":"v8tbl3af","method":"leave"},{"args":[10,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,10],"key":"70xvia1h","method":"depatch"},{"args":[1,10],"key":"70xvia1h","method":"depatch"},{"args":[2,10],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,11,15],"key":"70xvia1h","method":"patch"},{"args":[1,11,3],"key":"70xvia1h","method":"patch"},{"args":[2,11,4],"key":"70xvia1h","method":"patch"},{"args":[3,4],"key":"v8tbl3af","method":"visit"},{"args":[4,3],"key":"v8tbl3af","method":"visit"},{"args":[11,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[3,4],"key":"v8tbl3af","method":"leave"},{"args":[4,3],"key":"v8tbl3af","method":"leave"},{"args":[11,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[0,11],"key":"70xvia1h","method":"depatch"},{"args":[1,11],"key":"70xvia1h","method":"depatch"},{"args":[2,11],"key":"70xvia1h","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["初始化各结点的parent为自身"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[3,3],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[4,4],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[5,5],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[6,6],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["按序遍历边表,输出最小生成树的边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"v8tbl3af","method":"visit"},{"args":[3,0],"key":"v8tbl3af","method":"visit"},{"args":[1,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"v8tbl3af","method":"leave"},{"args":[3,0],"key":"v8tbl3af","method":"leave"},{"args":[1,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,0],"key":"0e91x4ib","method":"patch"},{"args":[3,3],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"0e91x4ib","method":"depatch"},{"args":[3],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"0e91x4ib","method":"select"},{"args":[3],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于不同的连通分量,合并"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"0e91x4ib","method":"depatch"},{"args":[0],"key":"0e91x4ib","method":"deselect"},{"args":[3],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"v8tbl3af","method":"visit"},{"args":[3,0],"key":"v8tbl3af","method":"visit"},{"args":[1,0,2],"key":"70xvia1h","method":"selectCol"},{"args":["选中: (0,3) 权值=5"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"v8tbl3af","method":"visit"},{"args":[4,2],"key":"v8tbl3af","method":"visit"},{"args":[2,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"v8tbl3af","method":"leave"},{"args":[4,2],"key":"v8tbl3af","method":"leave"},{"args":[2,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"0e91x4ib","method":"patch"},{"args":[4,4],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"0e91x4ib","method":"depatch"},{"args":[4],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"0e91x4ib","method":"select"},{"args":[4],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于不同的连通分量,合并"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4,2],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"0e91x4ib","method":"depatch"},{"args":[2],"key":"0e91x4ib","method":"deselect"},{"args":[4],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"v8tbl3af","method":"visit"},{"args":[4,2],"key":"v8tbl3af","method":"visit"},{"args":[2,0,2],"key":"70xvia1h","method":"selectCol"},{"args":["选中: (2,4) 权值=5"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,5],"key":"v8tbl3af","method":"visit"},{"args":[5,3],"key":"v8tbl3af","method":"visit"},{"args":[3,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[3,5],"key":"v8tbl3af","method":"leave"},{"args":[5,3],"key":"v8tbl3af","method":"leave"},{"args":[3,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"0e91x4ib","method":"patch"},{"args":[5,5],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"0e91x4ib","method":"depatch"},{"args":[5],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"0e91x4ib","method":"select"},{"args":[5],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于不同的连通分量,合并"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[5,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"0e91x4ib","method":"depatch"},{"args":[3],"key":"0e91x4ib","method":"deselect"},{"args":[5],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[3,5],"key":"v8tbl3af","method":"visit"},{"args":[5,3],"key":"v8tbl3af","method":"visit"},{"args":[3,0,2],"key":"70xvia1h","method":"selectCol"},{"args":["选中: (3,5) 权值=6"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"v8tbl3af","method":"visit"},{"args":[1,0],"key":"v8tbl3af","method":"visit"},{"args":[4,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"v8tbl3af","method":"leave"},{"args":[1,0],"key":"v8tbl3af","method":"leave"},{"args":[4,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0,0],"key":"0e91x4ib","method":"patch"},{"args":[1,1],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"0e91x4ib","method":"depatch"},{"args":[1],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"0e91x4ib","method":"select"},{"args":[1],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于不同的连通分量,合并"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"depatch"},{"args":[0],"key":"0e91x4ib","method":"deselect"},{"args":[1],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"v8tbl3af","method":"visit"},{"args":[1,0],"key":"v8tbl3af","method":"visit"},{"args":[4,0,2],"key":"70xvia1h","method":"selectCol"},{"args":["选中: (0,1) 权值=7"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"v8tbl3af","method":"visit"},{"args":[4,1],"key":"v8tbl3af","method":"visit"},{"args":[5,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"v8tbl3af","method":"leave"},{"args":[4,1],"key":"v8tbl3af","method":"leave"},{"args":[5,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"0e91x4ib","method":"patch"},{"args":[4,2],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"depatch"},{"args":[4],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"select"},{"args":[4],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于不同的连通分量,合并"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"0e91x4ib","method":"depatch"},{"args":[1],"key":"0e91x4ib","method":"deselect"},{"args":[4],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"v8tbl3af","method":"visit"},{"args":[4,1],"key":"v8tbl3af","method":"visit"},{"args":[5,0,2],"key":"70xvia1h","method":"selectCol"},{"args":["选中: (1,4) 权值=7"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"v8tbl3af","method":"visit"},{"args":[2,1],"key":"v8tbl3af","method":"visit"},{"args":[6,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"v8tbl3af","method":"leave"},{"args":[2,1],"key":"v8tbl3af","method":"leave"},{"args":[6,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"0e91x4ib","method":"patch"},{"args":[2,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"depatch"},{"args":[2],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"select"},{"args":[2],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于同一连通分量"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[1],"key":"0e91x4ib","method":"deselect"},{"args":[2],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4,5],"key":"v8tbl3af","method":"visit"},{"args":[5,4],"key":"v8tbl3af","method":"visit"},{"args":[7,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[4,5],"key":"v8tbl3af","method":"leave"},{"args":[5,4],"key":"v8tbl3af","method":"leave"},{"args":[7,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4,0],"key":"0e91x4ib","method":"patch"},{"args":[5,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"0e91x4ib","method":"depatch"},{"args":[5],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"0e91x4ib","method":"select"},{"args":[5],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于同一连通分量"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[7,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[4],"key":"0e91x4ib","method":"deselect"},{"args":[5],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"v8tbl3af","method":"visit"},{"args":[3,1],"key":"v8tbl3af","method":"visit"},{"args":[8,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"v8tbl3af","method":"leave"},{"args":[3,1],"key":"v8tbl3af","method":"leave"},{"args":[8,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"0e91x4ib","method":"patch"},{"args":[3,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"depatch"},{"args":[3],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"0e91x4ib","method":"select"},{"args":[3],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于同一连通分量"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[8,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[1],"key":"0e91x4ib","method":"deselect"},{"args":[3],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":["寻找下一条最短边"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4,6],"key":"v8tbl3af","method":"visit"},{"args":[6,4],"key":"v8tbl3af","method":"visit"},{"args":[9,0,2],"key":"70xvia1h","method":"selectCol"},{"args":[],"key":null,"method":"delay"},{"args":[4,6],"key":"v8tbl3af","method":"leave"},{"args":[6,4],"key":"v8tbl3af","method":"leave"},{"args":[9,0,2],"key":"70xvia1h","method":"deselectCol"},{"args":[],"key":null,"method":"delay"},{"args":["调用Find函数获取parent信息,并进行路径压缩"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4,0],"key":"0e91x4ib","method":"patch"},{"args":[6,6],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"0e91x4ib","method":"depatch"},{"args":[6],"key":"0e91x4ib","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"0e91x4ib","method":"select"},{"args":[6],"key":"0e91x4ib","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["两者属于不同的连通分量,合并"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"0e91x4ib","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"0e91x4ib","method":"depatch"},{"args":[4],"key":"0e91x4ib","method":"deselect"},{"args":[6],"key":"0e91x4ib","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,6],"key":"v8tbl3af","method":"visit"},{"args":[6,4],"key":"v8tbl3af","method":"visit"},{"args":[9,0,2],"key":"70xvia1h","method":"selectCol"},{"args":["选中: (4,6) 权值=9"],"key":"s6rphlb7","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["Kruskal算法运行结束,生成树中边的总权值: 39"],"key":"s6rphlb7","method":"println"}] \ No newline at end of file diff --git a/Finished/Prim/Prim.cpp b/Finished/Prim/Prim.cpp new file mode 100644 index 0000000..a90affb --- /dev/null +++ b/Finished/Prim/Prim.cpp @@ -0,0 +1,210 @@ +#include "algorithm-visualizer.h" +#include +#include +#include +#include +#include +#include + +using json = nlohmann::json; +int INF = std::numeric_limits::max(); +// Prim 算法:在单独函数中实现,保留变量命名和算法逻辑 +// G: 邻接矩阵(0 表示无边),start: 起始结点,默认为 0 +int Prim(std::vector> &C, int start, + GraphTracer &tracer, LogTracer &logger, Array2DTracer &arraytracer) +{ + int n = (int)C.size(); + std::vector CLOSEST(n, 0); // 记录U中的顶点 + std::vector LOWCOST(n, 0); // 最小边权值 + CLOSEST[start] = 0; + tracer.visit(start); // 标记起始结点 + logger.println("下面根据起始节点初始化 LOWCOST 和 CLOSEST 数组,第一行为CLOSEST数组,第二行为LOWCOST数组"); + Tracer::delay(); + arraytracer.patch(2, start+1, 0); + arraytracer.patch(1, start+1, 0); + Tracer::delay(); + arraytracer.depatch(2, start+1); + arraytracer.depatch(1, start+1); + Tracer::delay(); + + int i = 0, j = 0, k = 0; + for (i = 1; i < n; i++) + { + if (C[start][i] == 0) + { + LOWCOST[i] = INF; + CLOSEST[i] = -1; // 表示无连接 + arraytracer.patch(2, i+1, "INF"); + arraytracer.patch(1, i+1, "-"); + Tracer::delay(); + arraytracer.depatch(2, i+1); + arraytracer.depatch(1, i+1); + Tracer::delay(); + continue; + } + tracer.visit(start, i); + CLOSEST[i] = start; + LOWCOST[i] = C[start][i]; + arraytracer.patch(2, i+1, LOWCOST[i]); + arraytracer.patch(1, i+1, CLOSEST[i]); + Tracer::delay(); + tracer.leave(start, i); + arraytracer.depatch(2, i+1); + arraytracer.depatch(1, i+1); + Tracer::delay(); + } + LOWCOST[start] = 0; // 标记加入最小生成树 + + logger.println("下面开始执行 Prim 算法,遍历LOWCOST和CLOSEST数组以选择最小边"); + Tracer::delay(); + int sum = 0; + for (i = 1; i < n; i++) + { + int minweight = INF; + k = i; + // 遍历已在树中的结点和未加入的结点寻找最小边 + for (j = 1; j < n; j++) + { + if (LOWCOST[j] == INF || LOWCOST[j] == 0) + continue; + std::cout << "(CLOSEST[j], j) : (" << CLOSEST[j] << "," << j << ") 权值=" << LOWCOST[j] << std::endl; + tracer.visit(j, CLOSEST[j]); + arraytracer.select(2, j+1); + arraytracer.select(1, j+1); + Tracer::delay(); + if (LOWCOST[j] < minweight) + { + minweight = LOWCOST[j]; + k = j; + } + tracer.leave(j, CLOSEST[j]); + arraytracer.deselect(2, j+1); + arraytracer.deselect(1, j+1); + Tracer::delay(); + } + + tracer.visit(k, CLOSEST[k]); + arraytracer.select(2, k+1); + arraytracer.select(1, k+1); + Tracer::delay(); + arraytracer.deselect(2, k+1); + arraytracer.deselect(1, k+1); + tracer.leave(k, CLOSEST[k]); + Tracer::delay(); + tracer.visit(k, CLOSEST[k]); + arraytracer.select(2, k+1); + arraytracer.select(1, k+1); + logger.println(std::string("选中边: (") + std::to_string(CLOSEST[k]) + "," + std::to_string(k) + ") 权值=" + std::to_string(C[k][CLOSEST[k]])); + std::cout << "(" << CLOSEST[k] << "," << k << ") 权值=" << LOWCOST[k] << std::endl; + Tracer::delay(); + + sum += C[k][CLOSEST[k]]; + // 标记加入最小生成树 + C[k][CLOSEST[k]] = 0; + C[CLOSEST[k]][k] = 0; + LOWCOST[k] = 0; + logger.println("下面根据新加入的结点更新LOWCOST和CLOSEST数组"); + Tracer::delay(); + arraytracer.deselect(2, k+1); + arraytracer.deselect(1, k+1); + arraytracer.patch(1, k+1, CLOSEST[k]); + arraytracer.patch(2, k+1, 0); + Tracer::delay(); + arraytracer.depatch(1, k+1); + arraytracer.depatch(2, k+1); + Tracer::delay(); + for (j = 1; j < n; j++) + { + if (C[k][j] != 0 && C[k][j] < LOWCOST[j]) + { + LOWCOST[j] = C[k][j]; + CLOSEST[j] = k; + tracer.visit(k, j); + arraytracer.patch(1, j+1, CLOSEST[j]); + arraytracer.patch(2, j+1, LOWCOST[j]); + Tracer::delay(); + std::cout << "更新结点 " << j << " 的最小边为 (" << k << "," << j << ") 权值=" << C[k][j] << std::endl; + tracer.leave(k, j); + arraytracer.depatch(1, j+1); + arraytracer.depatch(2, j+1); + Tracer::delay(); + } + } + logger.println("数组更新完毕,继续寻找当前距离最小的边"); + Tracer::delay(); + } + + logger.println(std::string("算法执行完毕,生成树中的边权值之和: ") + std::to_string(sum)); + Tracer::delay(); + return sum; +} + +int main() +{ + // 使用固定的无向加权图作为测试样例(对称矩阵),规模为 8 个顶点 + // 节点: 0 1 2 3 4 5 6 7 + std::vector> C = { + {0, 2, 0, 6, 0, 0, 3, 0}, + {2, 0, 3, 8, 5, 0, 0, 0}, + {0, 3, 0, 0, 7, 4, 0, 0}, + {6, 8, 0, 0, 9, 0, 0, 1}, + {0, 5, 7, 9, 0, 2, 0, 0}, + {0, 0, 4, 0, 2, 0, 6, 0}, + {3, 0, 0, 0, 0, 6, 0, 5}, + {0, 0, 0, 1, 0, 0, 5, 0}}; + + // Tracers + GraphTracer tracer = GraphTracer("Prim算法").directed(false).weighted(); + LogTracer logger = LogTracer("运行日志"); + Array2DTracer arraytracer = Array2DTracer("LOWCOST+CLOSEST"); + + // 将 tracers 放到垂直布局 + Layout::setRoot(VerticalLayout({tracer, arraytracer, logger})); + + // 设置图到 tracer,并使用圆形布局以避免 tree 布局把节点排列在一条直线上 + json Cjson = json::array(); + for (auto &row : C) + { + json r = json::array(); + for (int v : row) + r.push_back(v); + Cjson.push_back(r); + } + tracer.set(Cjson); + // 使用圆形布局让节点均匀分布 + tracer.layoutCircle(); + Tracer::delay(); + + // 初始化 arraytracer 显示为 "-" / INF / values + int n = (int)C.size(); + json row_index = json::array(); + row_index.push_back("节点值"); + json row0 = json::array(), row1 = json::array(); + row0.push_back("CLOSEST数组"); + row1.push_back("LOWCOST数组"); + for (int i = 0; i < n; ++i) + { + row_index.push_back(std::to_string(i)); + row0.push_back(std::string("-")); + row1.push_back(std::string("-")); + } + json arr = json::array(); + arr.push_back(row_index); + arr.push_back(row0); + arr.push_back(row1); + arraytracer.set(arr); + Tracer::delay(); + + // 显示初始信息 + logger.println("开始运行 Prim 算法,起始点 0"); + Tracer::delay(); + + int total = Prim(C, 0, tracer, logger, arraytracer); + + logger.println(std::string("Prim 算法执行完毕,最小生成树总权值=") + std::to_string(total)); + + // 同时把找到的最小生成树的边(在可视化中也已经被打印)再次输出为总结 + logger.println("最小生成树边列表已输出(每行格式: (u,v) 权值)"); + + return 0; +} diff --git a/Finished/Prim/Prim.exe b/Finished/Prim/Prim.exe new file mode 100755 index 0000000..3585639 Binary files /dev/null and b/Finished/Prim/Prim.exe differ diff --git a/Finished/Prim/Prim.json b/Finished/Prim/Prim.json new file mode 100644 index 0000000..2a49aef --- /dev/null +++ b/Finished/Prim/Prim.json @@ -0,0 +1 @@ +[{"args":["Prim算法"],"key":"l0m6ksnl","method":"GraphTracer"},{"args":[false],"key":"l0m6ksnl","method":"directed"},{"args":[],"key":"l0m6ksnl","method":"weighted"},{"args":["运行日志"],"key":"08sc0qx1","method":"LogTracer"},{"args":["LOWCOST+CLOSEST"],"key":"j0i1f44x","method":"Array2DTracer"},{"args":[["l0m6ksnl","j0i1f44x","08sc0qx1"]],"key":"h4vsqo9u","method":"VerticalLayout"},{"args":["h4vsqo9u"],"key":null,"method":"setRoot"},{"args":[[[0,2,0,6,0,0,3,0],[2,0,3,8,5,0,0,0],[0,3,0,0,7,4,0,0],[6,8,0,0,9,0,0,1],[0,5,7,9,0,2,0,0],[0,0,4,0,2,0,6,0],[3,0,0,0,0,6,0,5],[0,0,0,1,0,0,5,0]]],"key":"l0m6ksnl","method":"set"},{"args":[],"key":"l0m6ksnl","method":"layoutCircle"},{"args":[],"key":null,"method":"delay"},{"args":[[["节点值","0","1","2","3","4","5","6","7"],["CLOSEST数组","-","-","-","-","-","-","-","-"],["LOWCOST数组","-","-","-","-","-","-","-","-"]]],"key":"j0i1f44x","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["开始运行 Prim 算法,起始点 0"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"l0m6ksnl","method":"visit"},{"args":["下面根据起始节点初始化 LOWCOST 和 CLOSEST 数组,第一行为CLOSEST数组,第二行为LOWCOST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,1,0],"key":"j0i1f44x","method":"patch"},{"args":[1,1,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"j0i1f44x","method":"depatch"},{"args":[1,1],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"l0m6ksnl","method":"visit"},{"args":[2,2,2],"key":"j0i1f44x","method":"patch"},{"args":[1,2,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"l0m6ksnl","method":"leave"},{"args":[2,2],"key":"j0i1f44x","method":"depatch"},{"args":[1,2],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,3,"INF"],"key":"j0i1f44x","method":"patch"},{"args":[1,3,"-"],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2,3],"key":"j0i1f44x","method":"depatch"},{"args":[1,3],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"l0m6ksnl","method":"visit"},{"args":[2,4,6],"key":"j0i1f44x","method":"patch"},{"args":[1,4,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"depatch"},{"args":[1,4],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,5,"INF"],"key":"j0i1f44x","method":"patch"},{"args":[1,5,"-"],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"j0i1f44x","method":"depatch"},{"args":[1,5],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,6,"INF"],"key":"j0i1f44x","method":"patch"},{"args":[1,6,"-"],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"j0i1f44x","method":"depatch"},{"args":[1,6],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"l0m6ksnl","method":"visit"},{"args":[2,7,3],"key":"j0i1f44x","method":"patch"},{"args":[1,7,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"l0m6ksnl","method":"leave"},{"args":[2,7],"key":"j0i1f44x","method":"depatch"},{"args":[1,7],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,8,"INF"],"key":"j0i1f44x","method":"patch"},{"args":[1,8,"-"],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2,8],"key":"j0i1f44x","method":"depatch"},{"args":[1,8],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["下面开始执行 Prim 算法,遍历LOWCOST和CLOSEST数组以选择最小边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,2],"key":"j0i1f44x","method":"select"},{"args":[1,2],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,2],"key":"j0i1f44x","method":"deselect"},{"args":[1,2],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,7],"key":"j0i1f44x","method":"select"},{"args":[1,7],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,7],"key":"j0i1f44x","method":"deselect"},{"args":[1,7],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,2],"key":"j0i1f44x","method":"select"},{"args":[1,2],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"j0i1f44x","method":"deselect"},{"args":[1,2],"key":"j0i1f44x","method":"deselect"},{"args":[1,0],"key":"l0m6ksnl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,2],"key":"j0i1f44x","method":"select"},{"args":[1,2],"key":"j0i1f44x","method":"select"},{"args":["选中边: (0,1) 权值=2"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["下面根据新加入的结点更新LOWCOST和CLOSEST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"j0i1f44x","method":"deselect"},{"args":[1,2],"key":"j0i1f44x","method":"deselect"},{"args":[1,2,0],"key":"j0i1f44x","method":"patch"},{"args":[2,2,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"j0i1f44x","method":"depatch"},{"args":[2,2],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"l0m6ksnl","method":"visit"},{"args":[1,3,1],"key":"j0i1f44x","method":"patch"},{"args":[2,3,3],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"l0m6ksnl","method":"leave"},{"args":[1,3],"key":"j0i1f44x","method":"depatch"},{"args":[2,3],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"l0m6ksnl","method":"visit"},{"args":[1,5,1],"key":"j0i1f44x","method":"patch"},{"args":[2,5,5],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"l0m6ksnl","method":"leave"},{"args":[1,5],"key":"j0i1f44x","method":"depatch"},{"args":[2,5],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["数组更新完毕,继续寻找当前距离最小的边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"l0m6ksnl","method":"visit"},{"args":[2,3],"key":"j0i1f44x","method":"select"},{"args":[1,3],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"l0m6ksnl","method":"leave"},{"args":[2,3],"key":"j0i1f44x","method":"deselect"},{"args":[1,3],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,1],"key":"l0m6ksnl","method":"visit"},{"args":[2,5],"key":"j0i1f44x","method":"select"},{"args":[1,5],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[4,1],"key":"l0m6ksnl","method":"leave"},{"args":[2,5],"key":"j0i1f44x","method":"deselect"},{"args":[1,5],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,7],"key":"j0i1f44x","method":"select"},{"args":[1,7],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,7],"key":"j0i1f44x","method":"deselect"},{"args":[1,7],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"l0m6ksnl","method":"visit"},{"args":[2,3],"key":"j0i1f44x","method":"select"},{"args":[1,3],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,3],"key":"j0i1f44x","method":"deselect"},{"args":[1,3],"key":"j0i1f44x","method":"deselect"},{"args":[2,1],"key":"l0m6ksnl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"l0m6ksnl","method":"visit"},{"args":[2,3],"key":"j0i1f44x","method":"select"},{"args":[1,3],"key":"j0i1f44x","method":"select"},{"args":["选中边: (1,2) 权值=3"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["下面根据新加入的结点更新LOWCOST和CLOSEST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,3],"key":"j0i1f44x","method":"deselect"},{"args":[1,3],"key":"j0i1f44x","method":"deselect"},{"args":[1,3,1],"key":"j0i1f44x","method":"patch"},{"args":[2,3,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"j0i1f44x","method":"depatch"},{"args":[2,3],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"l0m6ksnl","method":"visit"},{"args":[1,6,2],"key":"j0i1f44x","method":"patch"},{"args":[2,6,4],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"l0m6ksnl","method":"leave"},{"args":[1,6],"key":"j0i1f44x","method":"depatch"},{"args":[2,6],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["数组更新完毕,继续寻找当前距离最小的边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,1],"key":"l0m6ksnl","method":"visit"},{"args":[2,5],"key":"j0i1f44x","method":"select"},{"args":[1,5],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[4,1],"key":"l0m6ksnl","method":"leave"},{"args":[2,5],"key":"j0i1f44x","method":"deselect"},{"args":[1,5],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[5,2],"key":"l0m6ksnl","method":"visit"},{"args":[2,6],"key":"j0i1f44x","method":"select"},{"args":[1,6],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[5,2],"key":"l0m6ksnl","method":"leave"},{"args":[2,6],"key":"j0i1f44x","method":"deselect"},{"args":[1,6],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,7],"key":"j0i1f44x","method":"select"},{"args":[1,7],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,7],"key":"j0i1f44x","method":"deselect"},{"args":[1,7],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,7],"key":"j0i1f44x","method":"select"},{"args":[1,7],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,7],"key":"j0i1f44x","method":"deselect"},{"args":[1,7],"key":"j0i1f44x","method":"deselect"},{"args":[6,0],"key":"l0m6ksnl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[6,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,7],"key":"j0i1f44x","method":"select"},{"args":[1,7],"key":"j0i1f44x","method":"select"},{"args":["选中边: (0,6) 权值=3"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["下面根据新加入的结点更新LOWCOST和CLOSEST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,7],"key":"j0i1f44x","method":"deselect"},{"args":[1,7],"key":"j0i1f44x","method":"deselect"},{"args":[1,7,0],"key":"j0i1f44x","method":"patch"},{"args":[2,7,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"j0i1f44x","method":"depatch"},{"args":[2,7],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[6,7],"key":"l0m6ksnl","method":"visit"},{"args":[1,8,6],"key":"j0i1f44x","method":"patch"},{"args":[2,8,5],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[6,7],"key":"l0m6ksnl","method":"leave"},{"args":[1,8],"key":"j0i1f44x","method":"depatch"},{"args":[2,8],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["数组更新完毕,继续寻找当前距离最小的边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,1],"key":"l0m6ksnl","method":"visit"},{"args":[2,5],"key":"j0i1f44x","method":"select"},{"args":[1,5],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[4,1],"key":"l0m6ksnl","method":"leave"},{"args":[2,5],"key":"j0i1f44x","method":"deselect"},{"args":[1,5],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[5,2],"key":"l0m6ksnl","method":"visit"},{"args":[2,6],"key":"j0i1f44x","method":"select"},{"args":[1,6],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[5,2],"key":"l0m6ksnl","method":"leave"},{"args":[2,6],"key":"j0i1f44x","method":"deselect"},{"args":[1,6],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"visit"},{"args":[2,8],"key":"j0i1f44x","method":"select"},{"args":[1,8],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"leave"},{"args":[2,8],"key":"j0i1f44x","method":"deselect"},{"args":[1,8],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[5,2],"key":"l0m6ksnl","method":"visit"},{"args":[2,6],"key":"j0i1f44x","method":"select"},{"args":[1,6],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"j0i1f44x","method":"deselect"},{"args":[1,6],"key":"j0i1f44x","method":"deselect"},{"args":[5,2],"key":"l0m6ksnl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[5,2],"key":"l0m6ksnl","method":"visit"},{"args":[2,6],"key":"j0i1f44x","method":"select"},{"args":[1,6],"key":"j0i1f44x","method":"select"},{"args":["选中边: (2,5) 权值=4"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["下面根据新加入的结点更新LOWCOST和CLOSEST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,6],"key":"j0i1f44x","method":"deselect"},{"args":[1,6],"key":"j0i1f44x","method":"deselect"},{"args":[1,6,2],"key":"j0i1f44x","method":"patch"},{"args":[2,6,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"j0i1f44x","method":"depatch"},{"args":[2,6],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[5,4],"key":"l0m6ksnl","method":"visit"},{"args":[1,5,5],"key":"j0i1f44x","method":"patch"},{"args":[2,5,2],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[5,4],"key":"l0m6ksnl","method":"leave"},{"args":[1,5],"key":"j0i1f44x","method":"depatch"},{"args":[2,5],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["数组更新完毕,继续寻找当前距离最小的边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,5],"key":"l0m6ksnl","method":"visit"},{"args":[2,5],"key":"j0i1f44x","method":"select"},{"args":[1,5],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[4,5],"key":"l0m6ksnl","method":"leave"},{"args":[2,5],"key":"j0i1f44x","method":"deselect"},{"args":[1,5],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"visit"},{"args":[2,8],"key":"j0i1f44x","method":"select"},{"args":[1,8],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"leave"},{"args":[2,8],"key":"j0i1f44x","method":"deselect"},{"args":[1,8],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[4,5],"key":"l0m6ksnl","method":"visit"},{"args":[2,5],"key":"j0i1f44x","method":"select"},{"args":[1,5],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"j0i1f44x","method":"deselect"},{"args":[1,5],"key":"j0i1f44x","method":"deselect"},{"args":[4,5],"key":"l0m6ksnl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[4,5],"key":"l0m6ksnl","method":"visit"},{"args":[2,5],"key":"j0i1f44x","method":"select"},{"args":[1,5],"key":"j0i1f44x","method":"select"},{"args":["选中边: (5,4) 权值=2"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["下面根据新加入的结点更新LOWCOST和CLOSEST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,5],"key":"j0i1f44x","method":"deselect"},{"args":[1,5],"key":"j0i1f44x","method":"deselect"},{"args":[1,5,5],"key":"j0i1f44x","method":"patch"},{"args":[2,5,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"j0i1f44x","method":"depatch"},{"args":[2,5],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["数组更新完毕,继续寻找当前距离最小的边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3,0],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"visit"},{"args":[2,8],"key":"j0i1f44x","method":"select"},{"args":[1,8],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"leave"},{"args":[2,8],"key":"j0i1f44x","method":"deselect"},{"args":[1,8],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"visit"},{"args":[2,8],"key":"j0i1f44x","method":"select"},{"args":[1,8],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,8],"key":"j0i1f44x","method":"deselect"},{"args":[1,8],"key":"j0i1f44x","method":"deselect"},{"args":[7,6],"key":"l0m6ksnl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[7,6],"key":"l0m6ksnl","method":"visit"},{"args":[2,8],"key":"j0i1f44x","method":"select"},{"args":[1,8],"key":"j0i1f44x","method":"select"},{"args":["选中边: (6,7) 权值=5"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["下面根据新加入的结点更新LOWCOST和CLOSEST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,8],"key":"j0i1f44x","method":"deselect"},{"args":[1,8],"key":"j0i1f44x","method":"deselect"},{"args":[1,8,6],"key":"j0i1f44x","method":"patch"},{"args":[2,8,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,8],"key":"j0i1f44x","method":"depatch"},{"args":[2,8],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[7,3],"key":"l0m6ksnl","method":"visit"},{"args":[1,4,7],"key":"j0i1f44x","method":"patch"},{"args":[2,4,1],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[7,3],"key":"l0m6ksnl","method":"leave"},{"args":[1,4],"key":"j0i1f44x","method":"depatch"},{"args":[2,4],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["数组更新完毕,继续寻找当前距离最小的边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"l0m6ksnl","method":"leave"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[3,7],"key":"l0m6ksnl","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"l0m6ksnl","method":"visit"},{"args":[2,4],"key":"j0i1f44x","method":"select"},{"args":[1,4],"key":"j0i1f44x","method":"select"},{"args":["选中边: (7,3) 权值=1"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["下面根据新加入的结点更新LOWCOST和CLOSEST数组"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4],"key":"j0i1f44x","method":"deselect"},{"args":[1,4,7],"key":"j0i1f44x","method":"patch"},{"args":[2,4,0],"key":"j0i1f44x","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"j0i1f44x","method":"depatch"},{"args":[2,4],"key":"j0i1f44x","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":["数组更新完毕,继续寻找当前距离最小的边"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["算法执行完毕,生成树中的边权值之和: 20"],"key":"08sc0qx1","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":["Prim 算法执行完毕,最小生成树总权值=20"],"key":"08sc0qx1","method":"println"},{"args":["最小生成树边列表已输出(每行格式: (u,v) 权值)"],"key":"08sc0qx1","method":"println"}] \ No newline at end of file diff --git a/KMP-test.cpp b/KMP-test.cpp new file mode 100644 index 0000000..492edf8 --- /dev/null +++ b/KMP-test.cpp @@ -0,0 +1,220 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +void GetNext(const std::string &pattern, std::vector &_next, Array2DTracer &pattern_tracer, LogTracer &logger) +{ + int lenT = (int)pattern.size(); + int j = 1; // postfix pointer + int k = 0; // prefix pointer + + // visualize (offset columns by 1: column 0 reserved for header) + pattern_tracer.select(2, k + 1); + Tracer::delay(); + while (j < lenT) + { + if (k == 0 || pattern[j] == pattern[k]) + { + // visualize (column index = j+1) + pattern_tracer.select(1, j + 1); + Tracer::delay(); + + ++j; + ++k; + _next[j - 1] = k; + + // visualize + pattern_tracer.patch(0, j, k); + Tracer::delay(); + pattern_tracer.depatch(0, j); + Tracer::delay(); + pattern_tracer.deselect(1, j); + } + else + { + // visualize (column index = j+1) + pattern_tracer.select(1, j + 1); + Tracer::delay(); + + // visualize backtrack + logger.println(std::string("不匹配,k 从 ") + std::to_string(k) + " 回退到 Next[k-1] = " + std::to_string(_next[k - 1])); + pattern_tracer.select(0, k); // k-1 -> column k + Tracer::delay(); + pattern_tracer.deselect(2, k + 1); + pattern_tracer.select(2, _next[k - 1] + 1); + Tracer::delay(); + pattern_tracer.deselect(0, k); + + k = _next[k - 1]; + } + } + + // for (; j < lenT; ++j) + // { + // // visualize (column index = j+1) + // pattern_tracer.select(1, j + 1); + // Tracer::delay(); + + // while ((k > 0) && (pattern[j] != pattern[k])) + // { + // // visualize (adjust columns) + // pattern_tracer.select(0, k); // k-1 -> column k + // Tracer::delay(); + // pattern_tracer.deselect(2, k + 1); + // pattern_tracer.select(2, _next[k - 1] + 1); + // Tracer::delay(); + // pattern_tracer.deselect(0, k); + + // k = _next[k - 1]; + // } + // if (pattern[j] == pattern[k]) + // { + // // visualize + // pattern_tracer.deselect(2, k + 1); + // pattern_tracer.select(2, k + 2); + // Tracer::delay(); + // ++k; + // } + // // visualize + // pattern_tracer.patch(0, j + 1, k); + // Tracer::delay(); + // pattern_tracer.depatch(0, j + 1); + // Tracer::delay(); + // pattern_tracer.deselect(1, j + 1); + + // _next[j] = k; + // } + + // visualize final (deselect and set rows with header in column 0) + pattern_tracer.deselect(2, k + 1); + // set two rows: row_next and row_pat with header at column 0 + json row_next = json::array(); + row_next.push_back(std::string("Next值字符")); + for (int i = 0; i < lenT; ++i) row_next.push_back(0); + json row_patj = json::array(); + row_patj.push_back(std::string("模式字符j")); + for (int i = 0; i < lenT; ++i) row_patj.push_back(std::string(1, pattern[i])); + json row_patk = json::array(); + row_patk.push_back(std::string("模式字符k")); + for (int i = 0; i < lenT; ++i) row_patk.push_back(std::string(1, pattern[i])); + // duplicate pattern row for visualization (rows: next, pattern, pattern) + pattern_tracer.set(json::array({row_next, row_patj, row_patk})); + Tracer::delay(); +} + +void KMP(const std::string &str, const std::string &pattern, Array1DTracer &string_tracer, Array2DTracer &pattern_tracer, LogTracer &logger) +{ + std::vector match_positions; + int m = (int)pattern.size(); + + std::vector _next(m, 0); + // initial pattern tracer with 3 rows: _next, pattern, pattern (add header column at index 0) + json row_next = json::array(); + row_next.push_back(std::string("Next值字符")); + for (int i = 0; i < m; ++i) row_next.push_back(0); + json row_patj = json::array(); + row_patj.push_back(std::string("模式字符j")); + for (int i = 0; i < m; ++i) row_patj.push_back(std::string(1, pattern[i])); + json row_patk = json::array(); + row_patk.push_back(std::string("模式字符k")); + for (int i = 0; i < m; ++i) row_patk.push_back(std::string(1, pattern[i])); + // duplicate pattern row for visualization (rows: next, pattern, pattern) + pattern_tracer.set(json::array({row_next, row_patj, row_patk})); + Tracer::delay(); + + GetNext(pattern, _next, pattern_tracer, logger); + + int i = 0; // string pointer + int k = 0; // pattern pointer + for (; i < (int)str.size(); ++i) + { + // visualize (column offset +1) + string_tracer.select(i); + pattern_tracer.select(1, k + 1); + Tracer::delay(); + + while ((k > 0) && (str[i] != pattern[k])) + { + // visualize (adjust columns) + pattern_tracer.select(0, k); // k-1 -> column k + Tracer::delay(); + pattern_tracer.deselect(1, k + 1); + pattern_tracer.select(1, _next[k - 1] + 1); + Tracer::delay(); + pattern_tracer.deselect(0, k); + + k = _next[k - 1]; + } + if (str[i] == pattern[k]) + { + ++k; + if (k == m) + { + int match_start = i - m + 1; + match_positions.push_back(match_start); + // visualize match + string_tracer.select(match_start, match_start + m - 1); + Tracer::delay(); + string_tracer.deselect(match_start, match_start + m - 1); + Tracer::delay(); + + pattern_tracer.select(0, k); + Tracer::delay(); + pattern_tracer.deselect(1, k); + Tracer::delay(); + pattern_tracer.select(1, _next[k - 1] + 1); + Tracer::delay(); + pattern_tracer.deselect(0, k); + + k = _next[k - 1]; + } + else + { + pattern_tracer.deselect(1, k); + pattern_tracer.select(1, k + 1); + Tracer::delay(); + } + } + else + { + pattern_tracer.select(0, k + 1); + Tracer::delay(); + } + + pattern_tracer.deselect(0, k + 1); + pattern_tracer.deselect(1, k + 1); + string_tracer.deselect(i); + } + + // final highlight matches + for (int pos : match_positions) + { + string_tracer.select(pos, pos + m - 1); + Tracer::delay(); + string_tracer.deselect(pos, pos + m - 1); + } +} + +int main() +{ + const std::string str = "AAAABAABAAAABAAABAAAA"; + const std::string pattern = "AAAABAAA"; + + Array2DTracer pattern_tracer = Array2DTracer("模式"); + Array1DTracer string_tracer = Array1DTracer("目标串"); + LogTracer logger = LogTracer("运行日志"); + Layout::setRoot(VerticalLayout({pattern_tracer, string_tracer, logger})); + + // prepare string tracer array + json srow = json::array(); + for (char c : str) srow.push_back(std::string(1, c)); + string_tracer.set(srow); + + KMP(str, pattern, string_tracer, pattern_tracer, logger); + Tracer::delay(); + + return 0; +} diff --git a/KMP-test.exe b/KMP-test.exe new file mode 100755 index 0000000..51d6d17 Binary files /dev/null and b/KMP-test.exe differ diff --git a/KMP-test.json b/KMP-test.json new file mode 100644 index 0000000..171c8ee --- /dev/null +++ b/KMP-test.json @@ -0,0 +1 @@ +[{"args":["模式"],"key":"yazal5xm","method":"Array2DTracer"},{"args":["目标串"],"key":"oy7w96c4","method":"Array1DTracer"},{"args":["运行日志"],"key":"vjmtqucx","method":"LogTracer"},{"args":[["yazal5xm","oy7w96c4","vjmtqucx"]],"key":"fwsxx9p3","method":"VerticalLayout"},{"args":["fwsxx9p3"],"key":null,"method":"setRoot"},{"args":[["A","A","A","A","B","A","A","B","A","A","A","A","B","A","A","A","B","A","A","A","A"]],"key":"oy7w96c4","method":"set"},{"args":[[["Next值字符",0,0,0,0,0,0,0,0],["模式字符j","A","A","A","A","B","A","A","A"],["模式字符k","A","A","A","A","B","A","A","A"]]],"key":"yazal5xm","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2,1],"key":"yazal5xm","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"yazal5xm","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"yazal5xm","method":"deselect"},{"args":[1,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,3,2],"key":"yazal5xm","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"yazal5xm","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,4,3],"key":"yazal5xm","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"yazal5xm","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 3 回退到 Next[k-1] = 2"],"key":"vjmtqucx","method":"println"},{"args":[0,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,4],"key":"yazal5xm","method":"deselect"},{"args":[2,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 2 回退到 Next[k-1] = 1"],"key":"vjmtqucx","method":"println"},{"args":[0,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,3],"key":"yazal5xm","method":"deselect"},{"args":[2,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 1 回退到 Next[k-1] = 0"],"key":"vjmtqucx","method":"println"},{"args":[0,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"yazal5xm","method":"deselect"},{"args":[2,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,5,1],"key":"yazal5xm","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,5],"key":"yazal5xm","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"yazal5xm","method":"deselect"},{"args":[1,6],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,6,2],"key":"yazal5xm","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"yazal5xm","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[1,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,7,3],"key":"yazal5xm","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,7],"key":"yazal5xm","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"yazal5xm","method":"deselect"},{"args":[1,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,8,4],"key":"yazal5xm","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"depatch"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"yazal5xm","method":"deselect"},{"args":[2,5],"key":"yazal5xm","method":"deselect"},{"args":[[["Next值字符",0,0,0,0,0,0,0,0],["模式字符j","A","A","A","A","B","A","A","A"],["模式字符k","A","A","A","A","B","A","A","A"]]],"key":"yazal5xm","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"oy7w96c4","method":"select"},{"args":[1,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"yazal5xm","method":"deselect"},{"args":[1,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"yazal5xm","method":"deselect"},{"args":[1,2],"key":"yazal5xm","method":"deselect"},{"args":[0],"key":"oy7w96c4","method":"deselect"},{"args":[1],"key":"oy7w96c4","method":"select"},{"args":[1,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"yazal5xm","method":"deselect"},{"args":[1,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"yazal5xm","method":"deselect"},{"args":[1,3],"key":"yazal5xm","method":"deselect"},{"args":[1],"key":"oy7w96c4","method":"deselect"},{"args":[2],"key":"oy7w96c4","method":"select"},{"args":[1,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"deselect"},{"args":[2],"key":"oy7w96c4","method":"deselect"},{"args":[3],"key":"oy7w96c4","method":"select"},{"args":[1,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,5],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[3],"key":"oy7w96c4","method":"deselect"},{"args":[4],"key":"oy7w96c4","method":"select"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[1,6],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"yazal5xm","method":"deselect"},{"args":[1,6],"key":"yazal5xm","method":"deselect"},{"args":[4],"key":"oy7w96c4","method":"deselect"},{"args":[5],"key":"oy7w96c4","method":"select"},{"args":[1,6],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"yazal5xm","method":"deselect"},{"args":[1,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,7],"key":"yazal5xm","method":"deselect"},{"args":[1,7],"key":"yazal5xm","method":"deselect"},{"args":[5],"key":"oy7w96c4","method":"deselect"},{"args":[6],"key":"oy7w96c4","method":"select"},{"args":[1,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"yazal5xm","method":"deselect"},{"args":[1,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"deselect"},{"args":[1,8],"key":"yazal5xm","method":"deselect"},{"args":[6],"key":"oy7w96c4","method":"deselect"},{"args":[7],"key":"oy7w96c4","method":"select"},{"args":[1,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,8],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,7],"key":"yazal5xm","method":"deselect"},{"args":[0,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"yazal5xm","method":"deselect"},{"args":[1,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"yazal5xm","method":"deselect"},{"args":[0,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"yazal5xm","method":"deselect"},{"args":[1,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"yazal5xm","method":"deselect"},{"args":[0,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"yazal5xm","method":"deselect"},{"args":[1,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"yazal5xm","method":"deselect"},{"args":[0,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"yazal5xm","method":"deselect"},{"args":[1,1],"key":"yazal5xm","method":"deselect"},{"args":[7],"key":"oy7w96c4","method":"deselect"},{"args":[8],"key":"oy7w96c4","method":"select"},{"args":[1,1],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"yazal5xm","method":"deselect"},{"args":[1,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"yazal5xm","method":"deselect"},{"args":[1,2],"key":"yazal5xm","method":"deselect"},{"args":[8],"key":"oy7w96c4","method":"deselect"},{"args":[9],"key":"oy7w96c4","method":"select"},{"args":[1,2],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"yazal5xm","method":"deselect"},{"args":[1,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,3],"key":"yazal5xm","method":"deselect"},{"args":[1,3],"key":"yazal5xm","method":"deselect"},{"args":[9],"key":"oy7w96c4","method":"deselect"},{"args":[10],"key":"oy7w96c4","method":"select"},{"args":[1,3],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"deselect"},{"args":[10],"key":"oy7w96c4","method":"deselect"},{"args":[11],"key":"oy7w96c4","method":"select"},{"args":[1,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,5],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[11],"key":"oy7w96c4","method":"deselect"},{"args":[12],"key":"oy7w96c4","method":"select"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[1,6],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"yazal5xm","method":"deselect"},{"args":[1,6],"key":"yazal5xm","method":"deselect"},{"args":[12],"key":"oy7w96c4","method":"deselect"},{"args":[13],"key":"oy7w96c4","method":"select"},{"args":[1,6],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"yazal5xm","method":"deselect"},{"args":[1,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,7],"key":"yazal5xm","method":"deselect"},{"args":[1,7],"key":"yazal5xm","method":"deselect"},{"args":[13],"key":"oy7w96c4","method":"deselect"},{"args":[14],"key":"oy7w96c4","method":"select"},{"args":[1,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"yazal5xm","method":"deselect"},{"args":[1,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"deselect"},{"args":[1,8],"key":"yazal5xm","method":"deselect"},{"args":[14],"key":"oy7w96c4","method":"deselect"},{"args":[15],"key":"oy7w96c4","method":"select"},{"args":[1,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[8,15],"key":"oy7w96c4","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[8,15],"key":"oy7w96c4","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,8],"key":"yazal5xm","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"deselect"},{"args":[0,5],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[15],"key":"oy7w96c4","method":"deselect"},{"args":[16],"key":"oy7w96c4","method":"select"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[1,6],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"yazal5xm","method":"deselect"},{"args":[1,6],"key":"yazal5xm","method":"deselect"},{"args":[16],"key":"oy7w96c4","method":"deselect"},{"args":[17],"key":"oy7w96c4","method":"select"},{"args":[1,6],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"yazal5xm","method":"deselect"},{"args":[1,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,7],"key":"yazal5xm","method":"deselect"},{"args":[1,7],"key":"yazal5xm","method":"deselect"},{"args":[17],"key":"oy7w96c4","method":"deselect"},{"args":[18],"key":"oy7w96c4","method":"select"},{"args":[1,7],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,7],"key":"yazal5xm","method":"deselect"},{"args":[1,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"deselect"},{"args":[1,8],"key":"yazal5xm","method":"deselect"},{"args":[18],"key":"oy7w96c4","method":"deselect"},{"args":[19],"key":"oy7w96c4","method":"select"},{"args":[1,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[12,19],"key":"oy7w96c4","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[12,19],"key":"oy7w96c4","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,8],"key":"yazal5xm","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,8],"key":"yazal5xm","method":"deselect"},{"args":[0,5],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[19],"key":"oy7w96c4","method":"deselect"},{"args":[20],"key":"oy7w96c4","method":"select"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,4],"key":"yazal5xm","method":"deselect"},{"args":[1,4],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,5],"key":"yazal5xm","method":"deselect"},{"args":[1,5],"key":"yazal5xm","method":"deselect"},{"args":[20],"key":"oy7w96c4","method":"deselect"},{"args":[8,15],"key":"oy7w96c4","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[8,15],"key":"oy7w96c4","method":"deselect"},{"args":[12,19],"key":"oy7w96c4","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[12,19],"key":"oy7w96c4","method":"deselect"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/dijkstra.cpp b/dijkstra.cpp new file mode 100644 index 0000000..0372f0d --- /dev/null +++ b/dijkstra.cpp @@ -0,0 +1,109 @@ +// import visualization libraries { +#include "algorithm-visualizer.h" +// } +#include +#include +#include +using json = nlohmann::json; +// Tracers: graph, array1d (S) and log console +GraphTracer tracer = GraphTracer().directed(false).weighted().layoutCircle(); +Array1DTracer tracerS = Array1DTracer("Distances"); +LogTracer logger = LogTracer("Console"); +int main() +{ + const int N = 5; + // generate random graph like JS example: Randomize.Graph({ N: 5, ratio: 1, directed: false, weighted: true }) + std::vector Gmat(N * N); + Randomize::Integer randWeight(1, 9); + Randomize::Graph Ggen(N, 1.0, randWeight); + // do NOT chain these methods: they return by value, which would modify a temporary + // (so Ggen would keep its defaults). Call them separately to modify the original. + Ggen.directed(false); + Ggen.weighted(true); + Ggen.fill(Gmat.data()); + // convert to 2D vector for tracer.set + std::vector> G2(N, std::vector(N)); + for (int i = 0; i < N; ++i) + { + for (int j = 0; j < N; ++j) + { + G2[i][j] = Gmat[i * N + j]; + } + } + // initialize S (distance array) with INF + const int INF = std::numeric_limits::max(); + std::vector S(N, INF); + // layout and initial set + Layout::setRoot(VerticalLayout({tracer, tracerS, logger})); + tracer.log(logger); + tracer.set(G2); + // prepare display array for tracerS: use strings for INF, numbers otherwise + std::vector Sdisplay(N); + for (int i = 0; i < N; ++i) + Sdisplay[i] = "INF"; + tracerS.set(Sdisplay); + Tracer::delay(); + // pick random start and end (s != e) + Randomize::Integer randNode(0, N - 1); + int s = randNode.create(); + int e; + do + { + e = randNode.create(); + } while (e == s); + logger.println(std::string("finding the shortest path from ") + + std::to_string(s) + " to " + std::to_string(e)); + Tracer::delay(); + // Dijkstra + std::vector D(N, false); + S[s] = 0; + tracerS.patch(s, 0); + Tracer::delay(); + tracerS.depatch(s); + tracerS.select(s); + int k = N; + while (k--) + { + int minIndex = -1; + int minDistance = INF; + for (int i = 0; i < N; ++i) + { + if (!D[i] && S[i] < minDistance) + { + minDistance = S[i]; + minIndex = i; + } + } + if (minDistance == INF) + break; + D[minIndex] = true; + tracerS.select(minIndex); + tracer.visit(minIndex); + Tracer::delay(); + for (int i = 0; i < N; ++i) + { + if (G2[minIndex][i] && S[i] > S[minIndex] + G2[minIndex][i]) + { + S[i] = S[minIndex] + G2[minIndex][i]; + tracerS.patch(i, S[i]); + tracer.visit(i, minIndex, S[i]); + Tracer::delay(); + tracerS.depatch(i); + tracer.leave(i, minIndex); + Tracer::delay(); + } + } + tracer.leave(minIndex); + Tracer::delay(); + } + if (S[e] == INF) + { + logger.println(std::string("there is no path from ") + std::to_string(s) + " to " + std::to_string(e)); + } + else + { + logger.println(std::string("the shortest path from ") + std::to_string(s) + " to " + std::to_string(e) + " is " + std::to_string(S[e])); + } + Tracer::delay(); + return 0; +} \ No newline at end of file diff --git a/dijkstra.exe b/dijkstra.exe new file mode 100755 index 0000000..7bc969b Binary files /dev/null and b/dijkstra.exe differ diff --git a/dijkstra.json b/dijkstra.json new file mode 100644 index 0000000..e71ab29 --- /dev/null +++ b/dijkstra.json @@ -0,0 +1 @@ +[{"args":[],"key":"xz4dvuaz","method":"GraphTracer"},{"args":[false],"key":"xz4dvuaz","method":"directed"},{"args":[],"key":"xz4dvuaz","method":"weighted"},{"args":[],"key":"xz4dvuaz","method":"layoutCircle"},{"args":["Distances"],"key":"s018gupu","method":"Array1DTracer"},{"args":["Console"],"key":"eck71jw5","method":"LogTracer"},{"args":[["xz4dvuaz","s018gupu","eck71jw5"]],"key":"f2tdqrdu","method":"VerticalLayout"},{"args":["f2tdqrdu"],"key":null,"method":"setRoot"},{"args":["eck71jw5"],"key":"xz4dvuaz","method":"log"},{"args":[[[0,6,2,6,5],[6,0,4,5,8],[2,4,0,7,9],[6,5,7,0,4],[5,8,9,4,0]]],"key":"xz4dvuaz","method":"set"},{"args":[["INF","INF","INF","INF","INF"]],"key":"s018gupu","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["finding the shortest path from 2 to 4"],"key":"eck71jw5","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2,0],"key":"s018gupu","method":"patch"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"s018gupu","method":"depatch"},{"args":[2],"key":"s018gupu","method":"select"},{"args":[2],"key":"s018gupu","method":"select"},{"args":[2],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"s018gupu","method":"patch"},{"args":[0,2,2.0],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"s018gupu","method":"depatch"},{"args":[0,2],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"s018gupu","method":"patch"},{"args":[1,2,4.0],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"s018gupu","method":"depatch"},{"args":[1,2],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[3,7],"key":"s018gupu","method":"patch"},{"args":[3,2,7.0],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"s018gupu","method":"depatch"},{"args":[3,2],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[4,9],"key":"s018gupu","method":"patch"},{"args":[4,2,9.0],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"s018gupu","method":"depatch"},{"args":[4,2],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"s018gupu","method":"select"},{"args":[0],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[4,7],"key":"s018gupu","method":"patch"},{"args":[4,0,7.0],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"s018gupu","method":"depatch"},{"args":[4,0],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"s018gupu","method":"select"},{"args":[1],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"s018gupu","method":"select"},{"args":[3],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"s018gupu","method":"select"},{"args":[4],"key":"xz4dvuaz","method":"visit"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"xz4dvuaz","method":"leave"},{"args":[],"key":null,"method":"delay"},{"args":["the shortest path from 2 to 4 is 7"],"key":"eck71jw5","method":"println"},{"args":[],"key":null,"method":"delay"}] \ No newline at end of file diff --git a/pure_Prim b/pure_Prim new file mode 100755 index 0000000..6255b3d Binary files /dev/null and b/pure_Prim differ diff --git a/pure_Prim.cpp b/pure_Prim.cpp new file mode 100644 index 0000000..ab37180 --- /dev/null +++ b/pure_Prim.cpp @@ -0,0 +1,82 @@ +#include +using namespace std; + +const int INF = 1000000000; + +// 根据图片的伪代码,保留变量名和逻辑实现 Prim 算法 +// 使用 1-based 索引,C 为 (n+1)x(n+1) 的邻接矩阵,若无边则为 INF + +void Prim(int n, const vector>& C) +{ + vector LOWCOST(n+1); + vector CLOSSET(n+1); + int i, j, k; + int min; + + // 初始化 LOWCOST 和 CLOSSET + for (i = 2; i <= n; i++) { + LOWCOST[i] = C[1][i]; + CLOSSET[i] = 1; + } + + // 执行 n-1 次 + for (i = 2; i <= n; i++) { + // 在 LOWCOST 中选取最小边,记 CLOSET 中对应的顶点序号 k + min = LOWCOST[i]; + k = i; + for (j = 2; j <= n; j++) { + if (LOWCOST[j] < min) { + min = LOWCOST[j]; + k = j; + } + } + + // 输出顶点 k 和对应的权值(按图片中的格式) + cout << "(" << k << "," << CLOSSET[k] << ") 权值=" << min << endl; + + // 把顶点 k 加入最小生成树中(设置为 INF 表示已加入) + LOWCOST[k] = INF; + + // 调整数组 LOWCOST 和 CLOSSET + for (j = 2; j <= n; j++) { + if (C[k][j] < LOWCOST[j] && LOWCOST[j] != INF) { + LOWCOST[j] = C[k][j]; + CLOSSET[j] = k; + } + } + } +} + +int main() +{ + // 示例图(1-based),节点数 n + int n = 7; + // 构建 (n+1)x(n+1) 的邻接矩阵(无向图),无边用 INF + vector> C(n+1, vector(n+1, INF)); + + // 对角为 0 + for (int i = 1; i <= n; ++i) C[i][i] = 0; + + // 示例边(无向,互相赋值) + auto add_edge = [&](int u, int v, int w) { + C[u][v] = w; + C[v][u] = w; + }; + + add_edge(1,2,7); + add_edge(1,4,5); + add_edge(2,3,8); + add_edge(2,4,9); + add_edge(2,5,7); + add_edge(3,5,5); + add_edge(4,5,15); + add_edge(4,6,6); + add_edge(5,6,8); + add_edge(5,7,9); + add_edge(6,7,11); + + cout << "Running Prim (示例图),n=" << n << "\n"; + Prim(n, C); + + return 0; +} diff --git a/test.exe b/test.exe new file mode 100755 index 0000000..66c829e Binary files /dev/null and b/test.exe differ diff --git a/test/main.exe b/test/main.exe new file mode 100755 index 0000000..1c36cd5 Binary files /dev/null and b/test/main.exe differ diff --git a/test/visualization.json b/test/visualization.json new file mode 100644 index 0000000..d6122ba --- /dev/null +++ b/test/visualization.json @@ -0,0 +1 @@ +[{"args":["array"],"key":"vkx68cop","method":"Array1DTracer"},{"args":["array2d"],"key":"h3ecftue","method":"Array2DTracer"},{"args":[[[0,7,7,0,0],[7,0,0,0,5],[7,0,0,0,0],[0,0,0,0,8],[0,5,0,8,0]]],"key":"h3ecftue","method":"set"},{"args":[0,0,"aewg"],"key":"h3ecftue","method":"patch"},{"args":["chart"],"key":"v2f1ket8","method":"ChartTracer"},{"args":["graph"],"key":"jzyr8mek","method":"GraphTracer"},{"args":[[[0,7,7,0,0],[7,0,0,0,5],[7,0,0,0,0],[0,0,0,0,8],[0,5,0,8,0]]],"key":"jzyr8mek","method":"set"},{"args":["log"],"key":"hicb1zx5","method":"LogTracer"},{"args":["v2f1ket8"],"key":"vkx68cop","method":"chart"},{"args":["hicb1zx5"],"key":"jzyr8mek","method":"log"},{"args":[["jzyr8mek","hicb1zx5"]],"key":"5vb0x4s6","method":"HorizontalLayout"},{"args":[["vkx68cop","h3ecftue","v2f1ket8","5vb0x4s6"]],"key":"efe9zen8","method":"VerticalLayout"},{"args":["efe9zen8"],"key":null,"method":"setRoot"},{"args":["%s %d\n","cccc",1],"key":"hicb1zx5","method":"printf"},{"args":[],"key":null,"method":"delay"},{"args":["awegawebawea"],"key":"hicb1zx5","method":"println"}] \ No newline at end of file diff --git a/vision_KMP b/vision_KMP new file mode 100755 index 0000000..0dffd4a Binary files /dev/null and b/vision_KMP differ diff --git a/vision_KMP.cpp b/vision_KMP.cpp new file mode 100644 index 0000000..3761369 --- /dev/null +++ b/vision_KMP.cpp @@ -0,0 +1,198 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +using json = nlohmann::json; + +Array2DTracer pattern_tracer = Array2DTracer("模式"); // row0: Next, row1: pattern chars, row2: pointer/markers +Array1DTracer string_tracer = Array1DTracer("主串"); +LogTracer logger = LogTracer("运行日志"); + +// KMP 算法逻辑 +void GetNext(char* T, int Next[]) +{ + int lenT = std::strlen(T); // lenT为模式串T的长度 + int j = 0, k = -1; + if (lenT <= 0) return; + Next[0] = -1; + + // 可视化初始化:row0 Next (空),row1 pattern chars,row2 pointers + std::vector row0(lenT), row1(lenT), row2(lenT); + for (int idx = 0; idx < lenT; ++idx) { + row0[idx] = nullptr; + char tmp[2] = {T[idx], '\0'}; + row1[idx] = std::string(tmp); + row2[idx] = std::string(" "); + } + json arr = json::array(); + arr.push_back(row0); + arr.push_back(row1); + arr.push_back(row2); + pattern_tracer.set(arr); + + logger.println(std::string("开始计算 Next 数组,lenT=") + std::to_string(lenT)); + Tracer::delay(); + + while (j < lenT - 1) { + // 高亮当前比较位 j 和 k(在第1行为字符,高亮第2行用于指针) + if (k >= 0) pattern_tracer.select(2, k); + pattern_tracer.select(1, j); + Tracer::delay(); + + if (k == -1 || T[j] == T[k]) { + ++j; ++k; + Next[j] = k; + // 更新可视化 Next + pattern_tracer.patch(0, j, k); + logger.println(std::string("Next[") + std::to_string(j) + "] = " + std::to_string(k)); + Tracer::delay(); + // 取消高亮 j (字符行) + pattern_tracer.deselect(1, j-1); + } else { + // 不匹配时可视化回退 + logger.println(std::string("不匹配,k 从 ") + std::to_string(k) + " 回退到 Next[k] = " + std::to_string(Next[k])); + // 高亮 Next[k] 的位置 + if (k - 1 >= 0) { + pattern_tracer.select(0, k - 1); + Tracer::delay(); + pattern_tracer.deselect(0, k - 1); + } + k = Next[k]; + Tracer::delay(); + } + } + // 结束时去掉所有选择 + for (int i = 0; i < lenT; ++i) { + pattern_tracer.deselect(0, i); + pattern_tracer.deselect(1, i); + pattern_tracer.deselect(2, i); + } + Tracer::delay(); +} + +int StrMatch_KMP(char* S, char* T, int pos = 0) +{ + int lenS = std::strlen(S); + int lenT = std::strlen(T); + + if (lenT == 0) return pos; + if (pos < 0) pos = 0; + if (pos >= lenS) return -1; + + int* Next = new int[lenT]; + // 先计算 Next(内部含可视化) + GetNext(T, Next); + + // 初始化主串与 pattern_tracer 显示(确保 Next 行显示计算结果) + std::vector Sdisplay(lenS); + for (int i = 0; i < lenS; ++i) { + char tmp[2] = {S[i], '\0'}; + Sdisplay[i] = std::string(tmp); + } + string_tracer.set(Sdisplay); + + // 重新设置 pattern_tracer 行以反映计算好的 Next + std::vector row0(lenT), row1(lenT), row2(lenT); + for (int i = 0; i < lenT; ++i) { + row0[i] = Next[i]; + char tmp[2] = {T[i], '\0'}; + row1[i] = std::string(tmp); + row2[i] = std::string(" "); + } + json arr = json::array(); + arr.push_back(row0); + arr.push_back(row1); + arr.push_back(row2); + pattern_tracer.set(arr); + Tracer::delay(); + + int i = pos; + int j = 0; + + logger.println(std::string("开始匹配,主串长度=") + std::to_string(lenS) + ", 模式长度=" + std::to_string(lenT)); + Tracer::delay(); + + while (i < lenS && j < lenT) { + // 高亮主串与模式当前比较位置 + string_tracer.select(i); + pattern_tracer.select(1, j); + Tracer::delay(); + + if (j == -1 || S[i] == T[j]) { + ++i; ++j; + logger.println(std::string("匹配: S[") + std::to_string(i-1) + "] == T[" + std::to_string(j-1) + "]"); + Tracer::delay(); + } else { + logger.println(std::string("不匹配: S[") + std::to_string(i) + "] != T[" + std::to_string(j) + "],回退到 Next[j] = " + std::to_string(Next[j])); + // 可视化回退 + if (j - 1 >= 0) { + pattern_tracer.select(0, j - 1); + Tracer::delay(); + pattern_tracer.deselect(0, j - 1); + } + int newj = Next[j]; + pattern_tracer.deselect(1, j); + if (newj >= 0) { + pattern_tracer.select(1, newj); + Tracer::delay(); + pattern_tracer.deselect(1, newj); + } + j = newj; + Tracer::delay(); + } + // 去掉当前选择 + string_tracer.deselect(i-1 >= 0 ? i-1 : 0); + if (j >= 0 && j < lenT) pattern_tracer.deselect(1, j); + } + + delete[] Next; + + if (j == lenT) { + int res = i - lenT; + logger.println(std::string("匹配成功,起始下标 = ") + std::to_string(res)); + return res; + } else { + logger.println(std::string("匹配不成功")); + return -1; + } +} + +int main() +{ + const char S[] = "AAAABAABAAAABAAABAAAA"; + const char T[] = "AAAABAAA"; + + // 布局 + Layout::setRoot(VerticalLayout({pattern_tracer, string_tracer, logger})); + + // 初始显示 + std::vector Sdisplay(std::strlen(S)); + for (size_t i = 0; i < std::strlen(S); ++i) { + char tmp[2] = {S[i], '\0'}; + Sdisplay[i] = std::string(tmp); + } + string_tracer.set(Sdisplay); + + // 初始化 pattern_tracer with empty Next and pattern chars + int lt = std::strlen(T); + std::vector row0(lt), row1(lt), row2(lt); + for (int i = 0; i < lt; ++i) { + row0[i] = nullptr; + char tmp[2] = {T[i], '\0'}; + row1[i] = std::string(tmp); + row2[i] = std::string(" "); + } + json arr = json::array(); arr.push_back(row0); arr.push_back(row1); arr.push_back(row2); + pattern_tracer.set(arr); + Tracer::delay(); + + // 将 const away for our function signatures + char* Sbuf = const_cast(S); + char* Tbuf = const_cast(T); + + int pos = StrMatch_KMP(Sbuf, Tbuf, 0); + std::cout << "匹配结果位置: " << pos << std::endl; + + return 0; +} diff --git a/vision_visualization.json b/vision_visualization.json new file mode 100644 index 0000000..d78196c --- /dev/null +++ b/vision_visualization.json @@ -0,0 +1 @@ +[{"args":["Pattern"],"key":"ssv6jbdq","method":"Array2DTracer"},{"args":["String"],"key":"evvl4q49","method":"Array1DTracer"},{"args":["Console"],"key":"014vg64k","method":"LogTracer"},{"args":[["ssv6jbdq","evvl4q49","014vg64k"]],"key":"bvy1wxbw","method":"VerticalLayout"},{"args":["bvy1wxbw"],"key":null,"method":"setRoot"},{"args":[["A","A","A","A","B","A","A","B","A","A","A","A","B","A","A","A","B","A","A","A","A"]],"key":"evvl4q49","method":"set"},{"args":[[[null,null,null,null,null,null,null,null],["A","A","A","A","B","A","A","A"],[" "," "," "," "," "," "," "," "]]],"key":"ssv6jbdq","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":[[[null,null,null,null,null,null,null,null],["A","A","A","A","B","A","A","A"],[" "," "," "," "," "," "," "," "]]],"key":"ssv6jbdq","method":"set"},{"args":["开始计算 Next 数组,lenT=8"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,1,0],"key":"ssv6jbdq","method":"patch"},{"args":["Next[1] = 0"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"ssv6jbdq","method":"deselect"},{"args":[2,0],"key":"ssv6jbdq","method":"select"},{"args":[1,1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2,1],"key":"ssv6jbdq","method":"patch"},{"args":["Next[2] = 1"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"ssv6jbdq","method":"deselect"},{"args":[2,1],"key":"ssv6jbdq","method":"select"},{"args":[1,2],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,3,2],"key":"ssv6jbdq","method":"patch"},{"args":["Next[3] = 2"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"ssv6jbdq","method":"deselect"},{"args":[2,2],"key":"ssv6jbdq","method":"select"},{"args":[1,3],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,4,3],"key":"ssv6jbdq","method":"patch"},{"args":["Next[4] = 3"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,3],"key":"ssv6jbdq","method":"deselect"},{"args":[2,3],"key":"ssv6jbdq","method":"select"},{"args":[1,4],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 3 回退到 Next[k] = 2"],"key":"014vg64k","method":"println"},{"args":[0,2],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,2],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,2],"key":"ssv6jbdq","method":"select"},{"args":[1,4],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 2 回退到 Next[k] = 1"],"key":"014vg64k","method":"println"},{"args":[0,1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,1],"key":"ssv6jbdq","method":"select"},{"args":[1,4],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 1 回退到 Next[k] = 0"],"key":"014vg64k","method":"println"},{"args":[0,0],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,0],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[2,0],"key":"ssv6jbdq","method":"select"},{"args":[1,4],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配,k 从 0 回退到 Next[k] = -1"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,5,0],"key":"ssv6jbdq","method":"patch"},{"args":["Next[5] = 0"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,4],"key":"ssv6jbdq","method":"deselect"},{"args":[2,0],"key":"ssv6jbdq","method":"select"},{"args":[1,5],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,6,1],"key":"ssv6jbdq","method":"patch"},{"args":["Next[6] = 1"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,5],"key":"ssv6jbdq","method":"deselect"},{"args":[2,1],"key":"ssv6jbdq","method":"select"},{"args":[1,6],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,7,2],"key":"ssv6jbdq","method":"patch"},{"args":["Next[7] = 2"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1,6],"key":"ssv6jbdq","method":"deselect"},{"args":[0,0],"key":"ssv6jbdq","method":"deselect"},{"args":[1,0],"key":"ssv6jbdq","method":"deselect"},{"args":[2,0],"key":"ssv6jbdq","method":"deselect"},{"args":[0,1],"key":"ssv6jbdq","method":"deselect"},{"args":[1,1],"key":"ssv6jbdq","method":"deselect"},{"args":[2,1],"key":"ssv6jbdq","method":"deselect"},{"args":[0,2],"key":"ssv6jbdq","method":"deselect"},{"args":[1,2],"key":"ssv6jbdq","method":"deselect"},{"args":[2,2],"key":"ssv6jbdq","method":"deselect"},{"args":[0,3],"key":"ssv6jbdq","method":"deselect"},{"args":[1,3],"key":"ssv6jbdq","method":"deselect"},{"args":[2,3],"key":"ssv6jbdq","method":"deselect"},{"args":[0,4],"key":"ssv6jbdq","method":"deselect"},{"args":[1,4],"key":"ssv6jbdq","method":"deselect"},{"args":[2,4],"key":"ssv6jbdq","method":"deselect"},{"args":[0,5],"key":"ssv6jbdq","method":"deselect"},{"args":[1,5],"key":"ssv6jbdq","method":"deselect"},{"args":[2,5],"key":"ssv6jbdq","method":"deselect"},{"args":[0,6],"key":"ssv6jbdq","method":"deselect"},{"args":[1,6],"key":"ssv6jbdq","method":"deselect"},{"args":[2,6],"key":"ssv6jbdq","method":"deselect"},{"args":[0,7],"key":"ssv6jbdq","method":"deselect"},{"args":[1,7],"key":"ssv6jbdq","method":"deselect"},{"args":[2,7],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[["A","A","A","A","B","A","A","B","A","A","A","A","B","A","A","A","B","A","A","A","A"]],"key":"evvl4q49","method":"set"},{"args":[[[-1,0,1,2,3,0,1,2],["A","A","A","A","B","A","A","A"],[" "," "," "," "," "," "," "," "]]],"key":"ssv6jbdq","method":"set"},{"args":[],"key":null,"method":"delay"},{"args":["开始匹配,主串长度=21, 模式长度=8"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"evvl4q49","method":"select"},{"args":[1,0],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[0] == T[0]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[0],"key":"evvl4q49","method":"deselect"},{"args":[1,1],"key":"ssv6jbdq","method":"deselect"},{"args":[1],"key":"evvl4q49","method":"select"},{"args":[1,1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[1] == T[1]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[1],"key":"evvl4q49","method":"deselect"},{"args":[1,2],"key":"ssv6jbdq","method":"deselect"},{"args":[2],"key":"evvl4q49","method":"select"},{"args":[1,2],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[2] == T[2]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[2],"key":"evvl4q49","method":"deselect"},{"args":[1,3],"key":"ssv6jbdq","method":"deselect"},{"args":[3],"key":"evvl4q49","method":"select"},{"args":[1,3],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[3] == T[3]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[3],"key":"evvl4q49","method":"deselect"},{"args":[1,4],"key":"ssv6jbdq","method":"deselect"},{"args":[4],"key":"evvl4q49","method":"select"},{"args":[1,4],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[4] == T[4]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[4],"key":"evvl4q49","method":"deselect"},{"args":[1,5],"key":"ssv6jbdq","method":"deselect"},{"args":[5],"key":"evvl4q49","method":"select"},{"args":[1,5],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[5] == T[5]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[5],"key":"evvl4q49","method":"deselect"},{"args":[1,6],"key":"ssv6jbdq","method":"deselect"},{"args":[6],"key":"evvl4q49","method":"select"},{"args":[1,6],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[6] == T[6]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"evvl4q49","method":"deselect"},{"args":[1,7],"key":"ssv6jbdq","method":"deselect"},{"args":[7],"key":"evvl4q49","method":"select"},{"args":[1,7],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配: S[7] != T[7],回退到 Next[j] = 2"],"key":"014vg64k","method":"println"},{"args":[0,6],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,6],"key":"ssv6jbdq","method":"deselect"},{"args":[1,7],"key":"ssv6jbdq","method":"deselect"},{"args":[1,2],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,2],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"evvl4q49","method":"deselect"},{"args":[1,2],"key":"ssv6jbdq","method":"deselect"},{"args":[7],"key":"evvl4q49","method":"select"},{"args":[1,2],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配: S[7] != T[2],回退到 Next[j] = 1"],"key":"014vg64k","method":"println"},{"args":[0,1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,1],"key":"ssv6jbdq","method":"deselect"},{"args":[1,2],"key":"ssv6jbdq","method":"deselect"},{"args":[1,1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,1],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"evvl4q49","method":"deselect"},{"args":[1,1],"key":"ssv6jbdq","method":"deselect"},{"args":[7],"key":"evvl4q49","method":"select"},{"args":[1,1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配: S[7] != T[1],回退到 Next[j] = 0"],"key":"014vg64k","method":"println"},{"args":[0,0],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[0,0],"key":"ssv6jbdq","method":"deselect"},{"args":[1,1],"key":"ssv6jbdq","method":"deselect"},{"args":[1,0],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":[1,0],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"evvl4q49","method":"deselect"},{"args":[1,0],"key":"ssv6jbdq","method":"deselect"},{"args":[7],"key":"evvl4q49","method":"select"},{"args":[1,0],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["不匹配: S[7] != T[0],回退到 Next[j] = -1"],"key":"014vg64k","method":"println"},{"args":[1,0],"key":"ssv6jbdq","method":"deselect"},{"args":[],"key":null,"method":"delay"},{"args":[6],"key":"evvl4q49","method":"deselect"},{"args":[7],"key":"evvl4q49","method":"select"},{"args":[1,-1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[7] == T[-1]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[7],"key":"evvl4q49","method":"deselect"},{"args":[1,0],"key":"ssv6jbdq","method":"deselect"},{"args":[8],"key":"evvl4q49","method":"select"},{"args":[1,0],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[8] == T[0]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[8],"key":"evvl4q49","method":"deselect"},{"args":[1,1],"key":"ssv6jbdq","method":"deselect"},{"args":[9],"key":"evvl4q49","method":"select"},{"args":[1,1],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[9] == T[1]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[9],"key":"evvl4q49","method":"deselect"},{"args":[1,2],"key":"ssv6jbdq","method":"deselect"},{"args":[10],"key":"evvl4q49","method":"select"},{"args":[1,2],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[10] == T[2]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[10],"key":"evvl4q49","method":"deselect"},{"args":[1,3],"key":"ssv6jbdq","method":"deselect"},{"args":[11],"key":"evvl4q49","method":"select"},{"args":[1,3],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[11] == T[3]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[11],"key":"evvl4q49","method":"deselect"},{"args":[1,4],"key":"ssv6jbdq","method":"deselect"},{"args":[12],"key":"evvl4q49","method":"select"},{"args":[1,4],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[12] == T[4]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[12],"key":"evvl4q49","method":"deselect"},{"args":[1,5],"key":"ssv6jbdq","method":"deselect"},{"args":[13],"key":"evvl4q49","method":"select"},{"args":[1,5],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[13] == T[5]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[13],"key":"evvl4q49","method":"deselect"},{"args":[1,6],"key":"ssv6jbdq","method":"deselect"},{"args":[14],"key":"evvl4q49","method":"select"},{"args":[1,6],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[14] == T[6]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[14],"key":"evvl4q49","method":"deselect"},{"args":[1,7],"key":"ssv6jbdq","method":"deselect"},{"args":[15],"key":"evvl4q49","method":"select"},{"args":[1,7],"key":"ssv6jbdq","method":"select"},{"args":[],"key":null,"method":"delay"},{"args":["匹配: S[15] == T[7]"],"key":"014vg64k","method":"println"},{"args":[],"key":null,"method":"delay"},{"args":[15],"key":"evvl4q49","method":"deselect"},{"args":["匹配成功,起始下标 = 8"],"key":"014vg64k","method":"println"}] \ No newline at end of file diff --git a/visual_KMP b/visual_KMP new file mode 100755 index 0000000..3af9b83 Binary files /dev/null and b/visual_KMP differ diff --git a/visual_KMP.cpp b/visual_KMP.cpp new file mode 100644 index 0000000..e4d8848 --- /dev/null +++ b/visual_KMP.cpp @@ -0,0 +1,161 @@ +#include "algorithm-visualizer.h" +#include +#include +#include + +// 全局可视化对象(按照 dijkstra.cpp 的风格) +Array2DTracer pattern_tracer = Array2DTracer("Pattern"); // row0: Next, row1: pattern chars, row2: pointer/markers +Array1DTracer string_tracer = Array1DTracer("String"); +LogTracer logger = LogTracer("Console"); +// 保持与纯算法相同的函数签名和变量命名,仅插入可视化语句 +void GetNext(const std::string& Pattern, int Next[]) +{ + int lenT = Pattern.length(); // lenT为模式串T的长度 + int j = 0, k = -1; + if (lenT <= 0) return; + Next[0] = -1; + + logger.println(std::string("开始计算 Next 数组,lenT=") + std::to_string(lenT)); + Tracer::delay(); + + // 在 j < lenT 时扩展 Next,避免写出界 + while (j < lenT - 1) { + // 高亮比较位置 k 和 j(在 pattern_tracer 的第 2 行显示为指针) + // 显示当前 k 指针(在第三行展示为选中) + pattern_tracer.select(1, j); // 显示j位置 + Tracer::delay(); + + if (k == -1 || Pattern[j] == Pattern[k]) { + pattern_tracer.deselect(1, j); // 去掉j位置选中 + pattern_tracer.deselect(2, k); // 去掉k指针选中 + ++j; ++k; + Next[j] = k; + // 可视化:更新 Next[j] + pattern_tracer.select(1, j); // 显示更新后的j位置 + pattern_tracer.select(2, k); // 显示更新后的k指针位置 + Tracer::delay(); + pattern_tracer.patch(0, j, k); + Tracer::delay(); + pattern_tracer.depatch(0, j); + Tracer::delay(); + logger.println(std::string("Next[") + std::to_string(j) + "] = " + std::to_string(k)); + + } else { + // 可视化:说明回退到 Next[k] + logger.println(std::string("不匹配,k 从 ") + std::to_string(k) + " 回退到 Next[k] = " + std::to_string(Next[k])); + k = Next[k]; + pattern_tracer.select(0, k-1); + Tracer::delay(); + pattern_tracer.deselect(2, k); + pattern_tracer.select(2, Next[k-1]); + Tracer::delay(); + pattern_tracer.deselect(0, k-1); + Tracer::delay(); + } + } +} + +int StrMatch_KMP(const std::string& String, const std::string& Pattern, int pos = 0) +{ + // String 为主串, Pattern 为模式, 长度分别为了 lenS 和 lenT; 串采用顺序存储结构 + int lenS = String.length(); + int lenT = Pattern.length(); + + if (lenT == 0) return pos; // 空模式视为在 pos 处匹配 + if (pos < 0) pos = 0; + if (pos >= lenS) return -1; + + // 为 Next 数组分配空间,大小为 lenT(足够放置 0..lenT-1 的 Next) + int* Next = new int[lenT]; + + // 计算 Next + GetNext(Pattern, Next); + + // 可视化:确保 Next 数组完整显示(GetNext 在内部已更新 tracerNext) + Tracer::delay(); + + int i = pos; + int j = 0; // 从第一个位置开始比较 + + logger.println(std::string("开始匹配,主串长度=") + std::to_string(lenS + 0) + ", 模式长度=" + std::to_string(lenT)); + Tracer::delay(); + + while (i < lenS && j < lenT) { + // 可视化:选中当前比较位置(主串与模式) + string_tracer.select(i); + pattern_tracer.select(1, j); + Tracer::delay(); + + if (j == -1 || String[i] == Pattern[j]) { ++i; ++j; + logger.println(std::string("匹配: String[") + std::to_string(i-1) + "] == Pattern[" + std::to_string(j-1) + "]"); + Tracer::delay(); + } + else { + logger.println(std::string("不匹配: String[") + std::to_string(i) + "] != Pattern[" + std::to_string(j) + "], j 将回退到 Next[j] = " + std::to_string(Next[j])); + // 可视化回退:高亮 Next 的位置并移动指针行 + if (j - 1 >= 0) { + pattern_tracer.select(0, j - 1); + Tracer::delay(); + pattern_tracer.deselect(0, j - 1); + } + int newj = Next[j]; + pattern_tracer.select(2, (newj < 0 ? 0 : newj)); + Tracer::delay(); + pattern_tracer.deselect(2, (newj < 0 ? 0 : newj)); + j = newj; + Tracer::delay(); + } + } + + delete[] Next; + + if (j == lenT) { + int res = i - lenT; + logger.println(std::string("匹配成功,起始下标 = ") + std::to_string(res)); + return res; // 返回匹配的起始下标 + } + else { + logger.println(std::string("匹配不成功")); + return -1; // 匹配不成功 + } +} + +int main() +{ + // 示例测试 + const std::string String = "abxabcabcaby"; // 主串 + const std::string Pattern = "abcaby"; // 模式串 + + // 布局:模式串、主串、日志(垂直) + Layout::setRoot(VerticalLayout({pattern_tracer, string_tracer, logger})); + // 初始展示:主串与模式(pattern_tracer 在 StrMatch_KMP 内会被完整设置) + string_tracer.set(String); + // 为 pattern_tracer 做一个简要初始化(Next 行为-1,pattern 行为字符,指针行为空格) + int lt = Pattern.length(); + std::vector row0(lt), row1(lt), row2(lt); + for (int i = 0; i < lt; ++i) { + row0[i] = -1; + char tmp[2] = {Pattern[i], '\0'}; + row1[i] = std::string(tmp); + row2[i] = std::string(tmp); + } + nlohmann::json arr = nlohmann::json::array(); + arr.push_back(row0); + arr.push_back(row1); + arr.push_back(row2); + pattern_tracer.set(arr); + + Tracer::delay(); + + int pos = StrMatch_KMP(String, Pattern, 0); + if (pos >= 0) std::cout << "匹配成功,起始下标 = " << pos << std::endl; + else std::cout << "匹配失败" << std::endl; + + // // 另外一个示例,测试多次匹配起始位置 + // char S2[] = "ababababca"; + // char T2[] = "abababca"; + // int pos2 = StrMatch_KMP(S2, T2); + // std::cout << "示例2:" << (pos2>=0? std::to_string(pos2) : std::string("-1")) << std::endl; + + return 0; +}