基于Java Swing的智能数据结构可视化系统 | 支持自然语言交互的AI算法助手

🚀 基于Java Swing的智能数据结构可视化系统 | 支持自然语言交互的AI算法助手

技术栈 :Java Swing + Graphics2D + 正则表达式NLP + 图算法 + 动画系统
项目亮点 :自然语言创建图结构、6种核心算法动画演示、MVC架构设计
代码量 :5000+ 行纯Java实现
开源协议:MIT License


📌 前言

作为一名计算机专业的学生/开发者,你是否遇到过这些困扰?

  • 图算法概念抽象,纸上画图理解困难
  • DFS/BFS/Dijkstra 执行过程看不见摸不着
  • 排序算法背了原理,但不知道实际如何运行
  • ❌ 市面上的可视化工具要么功能单一 ,要么交互繁琐

于是我花了大量时间,用纯 Java 开发了这个 AlgoViz-AI 数据结构可视化系统!

✨ 最大亮点

支持自然语言交互! 不用点鼠标一个个添加节点,直接输入:

复制代码
创建一个包含节点A,B,C,D,E的无向图,边为<A,B,10>、<B,C,15>、<C,D,20>

系统自动解析并创建出完整的图结构,布局优化,一步到位!🎯


🎬 效果展示

1️⃣ AI 智能助手对话界面

复制代码
用户输入:创建无向图,顶点1,2,3,4,5,边<1,2,10>、<1,3,20>、<2,4,15>、<3,5,25>

系统响应:✓ 已创建无向图
         - 5 个节点
         - 4 条边
         - 自动优化布局完成
         
用户输入:运行Dijkstra算法,从节点1到节点5

系统响应:◆ 正在执行 Dijkstra 最短路径算法
         - 起点:1
         - 终点:5
         - 最短路径:1 → 3 → 5
         - 总距离:45

2️⃣ 图算法动画效果

  • 节点颜色变化:蓝色(未访问)→ 红色(正在访问)→ 绿色(已访问)
  • 边的高亮:遍历的边变为红色加粗显示
  • 实时步骤说明:每一步都有详细文字描述
  • 可调速度:1-10 级速度滑块,想看多慢就多慢

3️⃣ 排序算法柱状图

  • 数值柱形图:直观显示数组元素大小
  • 多色标记:红色(比较)、黄色(交换)、绿色(有序)
  • 步骤计数:显示"第 45 步:将元素 23 插入位置 3"

🛠️ 技术栈详解

核心技术架构

复制代码
┌─────────────────────────────────────────┐
│       Java Swing GUI Framework          │
├─────────────────────────────────────────┤
│  Model 层   │  View 层   │  Controller  │
├─────────────┼────────────┼──────────────┤
│  Graph      │ GraphPanel │ DataStruct-  │
│  SortAlgo   │ SortPanel  │ Visualizer   │
│  Algorithms │ AIChatUI   │ Executor     │
└─────────────┴────────────┴──────────────┘
         ↓            ↓            ↓
    数据结构      可视化       命令解析

1. GUI 层:Java Swing + Graphics2D

为什么选择 Swing?

  • ✅ 轻量级,无需额外依赖
  • ✅ 跨平台,一次编写处处运行
  • ✅ Graphics2D 提供强大的 2D 绘图能力

关键技术点

java 复制代码
// 1. 抗锯齿渲染,让图形更平滑
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                     RenderingHints.VALUE_ANTIALIAS_ON);

// 2. 绘制带箭头的有向边
int dx = x2 - x1;
int dy = y2 - y1;
double angle = Math.atan2(dy, dx);
g2d.drawLine(x1, y1, x2, y2);
// 绘制箭头...

// 3. 动画定时器
Timer timer = new Timer(speed, e -> {
    currentStep++;
    repaint();  // 触发重绘
});

2. 数据结构层:双重存储系统

创新点:同时维护邻接矩阵和邻接表!

java 复制代码
public class Graph {
    // 存储方式1:邻接矩阵(O(1)查询)
    private int[][] adjacencyMatrix;
    
    // 存储方式2:邻接表(节省空间)
    private Map<Integer, List<Edge>> adjacencyList;
    
    // 节点和边
    private List<Node> nodes;
    private List<Edge> edges;
    
    // 添加边时同步更新
    public void addEdge(int from, int to, int weight) {
        adjacencyMatrix[from][to] = weight;
        adjacencyList.get(from).add(new Edge(from, to, weight));
        
        if (!isDirected) {  // 无向图
            adjacencyMatrix[to][from] = weight;
            adjacencyList.get(to).add(new Edge(to, from, weight));
        }
    }
}

优势

  • 用户可以实时查看两种存储结构
  • 教学时对比演示不同存储方式的差异

3. 算法层:步骤记录系统

核心思想:算法执行时不直接修改图,而是记录每一步的状态!

java 复制代码
public class GraphAlgorithms {
    // 算法步骤记录类
    public static class AlgorithmStep {
        String description;       // 步骤描述
        int currentNode;          // 当前节点
        Set<Integer> visitedNodes; // 已访问节点
        List<Edge> highlightEdges; // 高亮的边
        String queueOrStack;      // 队列/栈状态
    }
    
    // DFS 算法示例
    public static List<AlgorithmStep> dfs(Graph graph, int start) {
        List<AlgorithmStep> steps = new ArrayList<>();
        Set<Integer> visited = new HashSet<>();
        Stack<Integer> stack = new Stack<>();
        
        stack.push(start);
        steps.add(new AlgorithmStep("初始化栈,压入起点 " + start, 
                   start, new HashSet<>(), new ArrayList<>(), 
                   "栈: [" + start + "]"));
        
        while (!stack.isEmpty()) {
            int node = stack.pop();
            if (!visited.contains(node)) {
                visited.add(node);
                
                // 记录这一步
                steps.add(new AlgorithmStep(
                    "访问节点 " + node,
                    node, 
                    new HashSet<>(visited),
                    getCurrentEdges(),
                    "栈: " + stack
                ));
                
                // 继续遍历...
            }
        }
        return steps;
    }
}

可视化效果

  • 动画播放器逐步读取 steps 列表
  • 根据每个 AlgorithmStep 渲染节点颜色和边状态
  • 显示队列/栈的实时内容

4. NLP 解析层:正则表达式引擎

问题:如何让用户用自然语言创建图?

解决方案:基于正则表达式的模式匹配!

java 复制代码
public class NLPGraphParser {
    // 1. 识别命令类型
    private static String detectCommandType(String input) {
        if (input.matches(".*(创建|生成|构建).*图.*")) {
            return "CREATE_GRAPH";
        }
        if (input.matches(".*(运行|执行|演示).*(DFS|BFS|Dijkstra|Prim|Kruskal).*")) {
            return "RUN_ALGORITHM";
        }
        if (input.matches(".*(添加|增加).*边.*")) {
            return "ADD_EDGE";
        }
        return "UNKNOWN";
    }
    
    // 2. 提取节点(支持数字和字母)
    private static List<String> extractNodes(String input) {
        List<String> nodes = new ArrayList<>();
        
        // 匹配 "顶点1,2,3,4" 或 "节点A,B,C,D"
        Pattern p = Pattern.compile("顶点[::】]?\\s*([\\d\\w,,、\\s]+)");
        Matcher m = p.matcher(input);
        
        if (m.find()) {
            String nodeStr = m.group(1);
            // 分割并清洗
            for (String node : nodeStr.split("[,,、\\s]+")) {
                nodes.add(node.trim());
            }
        }
        return nodes;
    }
    
    // 3. 提取边(支持 <A,B,10> 格式)
    private static List<EdgeInfo> extractEdges(String input) {
        List<EdgeInfo> edges = new ArrayList<>();
        
        // 正则匹配 <X,Y,W> 或 <X,Y>
        Pattern p = Pattern.compile(
            "<([\\w\\d]+)\\s*,\\s*([\\w\\d]+)(?:\\s*,\\s*(\\d+))?>");
        Matcher m = p.matcher(input);
        
        while (m.find()) {
            String from = m.group(1);
            String to = m.group(2);
            int weight = m.group(3) != null ? 
                         Integer.parseInt(m.group(3)) : 1;
            
            edges.add(new EdgeInfo(
                parseNodeId(from),  // A→0, B→1, 1→1
                parseNodeId(to),
                weight
            ));
        }
        return edges;
    }
    
    // 字母转数字:A→0, B→1, Z→25
    private static int parseNodeId(String nodeStr) {
        if (nodeStr.matches("\\d+")) {
            return Integer.parseInt(nodeStr);
        } else if (nodeStr.matches("[A-Za-z]")) {
            return Character.toUpperCase(nodeStr.charAt(0)) - 'A';
        }
        return -1;
    }
}

支持的语法示例

复制代码
✅ 创建无向图,顶点:1,2,3,4,边:<1,2,10>、<2,3,15>
✅ 生成有向图,节点A B C D,边<A,B>、<B,C>、<C,D>
✅ 添加边<3,5,20>
✅ 运行DFS算法从节点0开始
✅ 运行Dijkstra算法,起点1,终点5

5. 动画系统:基于 Timer 的状态机

java 复制代码
public class AnimatedCommandExecutor {
    private javax.swing.Timer animationTimer;
    private List<AlgorithmStep> steps;
    private int currentStep = 0;
    
    public void startAnimation(List<AlgorithmStep> steps) {
        this.steps = steps;
        this.currentStep = 0;
        
        // 创建定时器(每 500ms 执行一步)
        animationTimer = new Timer(500, e -> {
            if (currentStep < steps.size()) {
                applyStep(steps.get(currentStep));
                currentStep++;
                graphPanel.repaint();
            } else {
                ((Timer) e.getSource()).stop();
                onAnimationComplete();
            }
        });
        
        animationTimer.start();
    }
    
    private void applyStep(AlgorithmStep step) {
        // 更新节点颜色
        graphPanel.setHighlightedNodes(step.visitedNodes);
        graphPanel.setCurrentNode(step.currentNode);
        
        // 更新边的状态
        graphPanel.setHighlightedEdges(step.highlightEdges);
        
        // 更新描述文本
        graphPanel.setStepDescription(step.description);
    }
}

🎯 核心功能实现

功能1:Dijkstra 最短路径算法

算法实现(关键代码):

java 复制代码
public static List<AlgorithmStep> dijkstraShortestPath(
    Graph graph, int start, int end) {
    
    List<AlgorithmStep> steps = new ArrayList<>();
    int n = graph.getMaxNodes();
    
    // 初始化距离数组和前驱数组
    int[] dist = new int[n];
    int[] prev = new int[n];
    Arrays.fill(dist, Integer.MAX_VALUE);
    Arrays.fill(prev, -1);
    dist[start] = 0;
    
    // 优先队列(小根堆)
    PriorityQueue<int[]> pq = new PriorityQueue<>(
        Comparator.comparingInt(a -> a[1]));
    pq.offer(new int[]{start, 0});
    
    Set<Integer> visited = new HashSet<>();
    
    steps.add(new AlgorithmStep(
        "初始化:起点 " + start + " 距离为 0,其余为 ∞",
        start, new HashSet<>(), new ArrayList<>(), ""
    ));
    
    while (!pq.isEmpty()) {
        int[] current = pq.poll();
        int u = current[0];
        int currentDist = current[1];
        
        if (visited.contains(u)) continue;
        visited.add(u);
        
        steps.add(new AlgorithmStep(
            String.format("从优先队列取出节点 %d(距离=%d)", u, currentDist),
            u, new HashSet<>(visited), new ArrayList<>(), 
            "当前最短距离: " + Arrays.toString(dist)
        ));
        
        // 松弛操作
        for (Graph.Edge edge : graph.getAdjacencyList().get(u)) {
            int v = edge.to;
            int weight = edge.weight;
            
            if (dist[u] + weight < dist[v]) {
                dist[v] = dist[u] + weight;
                prev[v] = u;
                pq.offer(new int[]{v, dist[v]});
                
                steps.add(new AlgorithmStep(
                    String.format("松弛边 <%d,%d>: dist[%d] 更新为 %d", 
                                  u, v, v, dist[v]),
                    u, new HashSet<>(visited), 
                    List.of(edge), ""
                ));
            }
        }
        
        // 如果到达终点,提前结束
        if (u == end) break;
    }
    
    // 构建最短路径
    List<Integer> path = new ArrayList<>();
    for (int at = end; at != -1; at = prev[at]) {
        path.add(0, at);
    }
    
    // 添加最终汇总步骤(HTML格式,支持换行)
    StringBuilder summary = new StringBuilder();
    summary.append("<html><b>◆ Dijkstra 最短路径算法完成</b><br>");
    summary.append(String.format("<b>起点:%d | 终点:%d</b><br><br>", start, end));
    summary.append("<b>【最短距离】</b><br>");
    
    for (int i = 0; i < n; i++) {
        if (graph.getNodes().stream().anyMatch(node -> node.id == i)) {
            String distStr = (dist[i] == Integer.MAX_VALUE) ? 
                             "∞" : String.valueOf(dist[i]);
            summary.append(String.format("节点 %d: %s<br>", i, distStr));
        }
    }
    
    summary.append("<br><b>【最短路径】</b><br>");
    summary.append("路径: " + path.toString() + "<br>");
    summary.append(String.format("总距离: %d", dist[end]));
    summary.append("</html>");
    
    steps.add(new AlgorithmStep(
        summary.toString(),
        end, visited, new ArrayList<>(), ""
    ));
    
    return steps;
}

可视化效果

  1. 从起点开始,节点逐个变绿(已访问)
  2. 每次松弛边时,边变红闪烁
  3. 最终路径用粗红线标出
  4. 右侧显示 HTML 格式的汇总信息(支持换行和加粗)

功能2:图的保存与加载

自定义文本格式

复制代码
Directed:false
Nodes:5
Node 0:A 100,200
Node 1:B 250,150
Node 2:C 400,200
Node 3:D 250,350
Node 4:E 550,250
Edges:6
Edge 0:1 10
Edge 0:2 15
Edge 1:3 20
Edge 2:4 25
Edge 3:4 30
Edge 1:2 12

序列化代码

java 复制代码
public class GraphSerializer {
    public static boolean saveToFile(Graph graph, File file) {
        try (BufferedWriter writer = new BufferedWriter(
            new FileWriter(file))) {
            
            // 1. 写入图类型
            writer.write("Directed:" + graph.isDirected() + "\n");
            
            // 2. 写入节点信息
            writer.write("Nodes:" + graph.getNodes().size() + "\n");
            for (Graph.Node node : graph.getNodes()) {
                writer.write(String.format("Node %d:%s %d,%d\n",
                    node.id, node.label, 
                    node.position.x, node.position.y));
            }
            
            // 3. 写入边信息
            writer.write("Edges:" + graph.getEdges().size() + "\n");
            for (Graph.Edge edge : graph.getEdges()) {
                writer.write(String.format("Edge %d:%d %d\n",
                    edge.from, edge.to, edge.weight));
            }
            
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    public static Graph loadFromFile(File file) {
        // 反序列化逻辑(省略)...
    }
}

亮点

  • ✅ 纯文本格式,可直接编辑
  • ✅ 保存节点位置,重新打开布局不变
  • ✅ JFileChooser 记住上次使用的目录

功能3:无向图边的去重处理

问题 :无向图中,边 <1,3><3,1> 是同一条边,但如何避免重复添加?

解决方案

java 复制代码
public class Graph {
    public boolean addEdge(int from, int to, int weight) {
        // 检查边是否已存在
        for (Edge edge : edges) {
            if (isDirected) {
                // 有向图:只检查 from→to
                if (edge.from == from && edge.to == to) {
                    return false;  // 已存在
                }
            } else {
                // 无向图:检查 from↔to 和 to↔from
                if ((edge.from == from && edge.to == to) ||
                    (edge.from == to && edge.to == from)) {
                    return false;  // 已存在
                }
            }
        }
        
        // 添加边
        edges.add(new Edge(from, to, weight, isDirected));
        adjacencyMatrix[from][to] = weight;
        adjacencyList.get(from).add(new Edge(from, to, weight, isDirected));
        
        if (!isDirected) {
            adjacencyMatrix[to][from] = weight;
            adjacencyList.get(to).add(new Edge(to, from, weight, isDirected));
        }
        
        return true;
    }
}

📊 项目架构设计

MVC 模式实践

复制代码
┌─────────────────────────────────────────────────┐
│              DataStructureVisualizer            │  ← Controller
│              (主窗口 & 事件调度)                 │
└────────────────┬────────────────────────────────┘
                 │
        ┌────────┴────────┐
        ↓                 ↓
┌──────────────┐   ┌──────────────┐
│  GraphPanel  │   │ SortingPanel │               ← View
│  (图可视化)  │   │ (排序可视化) │
└──────┬───────┘   └──────┬───────┘
       │                  │
       ↓                  ↓
┌──────────────┐   ┌──────────────┐
│    Graph     │   │ SortAlgorithms│              ← Model
│ (图数据结构) │   │ (排序算法)   │
└──────────────┘   └──────────────┘

文件组织结构

复制代码
AlgoViz-AI/
├── Main.java                    # 程序入口
├── DataStructureVisualizer.java # 主控制器(900行)
│
├── 图模块/
│   ├── Graph.java               # 图数据结构(400行)
│   ├── GraphPanel.java          # 图可视化(700行)
│   ├── GraphAlgorithms.java     # 图算法(500行)
│   ├── GraphSerializer.java     # 图序列化(200行)
│   ├── GraphCommand.java        # 命令对象(120行)
│   ├── NLPGraphParser.java      # NLP解析器(350行)
│   └── GraphCommandExecutor.java# 命令执行器(200行)
│
├── 排序模块/
│   ├── SortAlgorithms.java      # 排序算法(180行)
│   └── SortingPanel.java        # 排序可视化(400行)
│
├── AI交互模块/
│   ├── AIChatPanel.java         # AI聊天面板(600行)
│   ├── ConversationHistory.java # 对话历史(150行)
│   ├── UnifiedNLPParser.java    # 统一解析器(250行)
│   └── AnimatedCommandExecutor.java # 动画执行器(300行)
│
└── 文档/
    ├── 用户手册.md
    ├── 快速开始.md
    └── LICENSE

总代码量:5000+ 行纯 Java


🌟 项目亮点

1. 自然语言交互(最大创新)

技术难点

  • 用户输入千变万化:"创建图"、"生成图"、"构建图"都要识别
  • 节点可以是数字(1,2,3)或字母(A,B,C)
  • 边的格式多样:<A,B,10><A,B>A-B

解决方案

  • 正则表达式模式库(30+ 个匹配规则)
  • 灵活的分词和清洗算法
  • 字母到数字的智能映射(A→0, Z→25)

2. 双重存储结构展示

教学价值

  • 学生可以直观对比邻接矩阵和邻接表的差异
  • 点击按钮即可切换查看

3. HTML 富文本支持

问题:Dijkstra 算法的结果太长,显示不全

解决

java 复制代码
// 使用 HTML 标签实现多行显示和加粗
String html = "<html><b>结果:</b><br>" +
              "节点0: 0<br>" +
              "节点1: 10<br>" +
              "节点2: 25<br></html>";

// 自定义渲染引擎解析 HTML
String[] lines = html.replaceAll("<html>|</html>", "")
                     .split("<br>");
for (int i = 0; i < lines.length; i++) {
    String line = lines[i].replaceAll("<b>|</b>", "");
    g2d.drawString(line, x, y + i * 20);
}

4. 智能布局算法

问题:用户一次创建 10 个节点,如何避免重叠?

解决

java 复制代码
// 圆形布局算法
int centerX = panelWidth / 2;
int centerY = panelHeight / 2;
int radius = Math.min(centerX, centerY) - 50;

for (int i = 0; i < nodeCount; i++) {
    double angle = 2 * Math.PI * i / nodeCount;
    int x = centerX + (int)(radius * Math.cos(angle));
    int y = centerY + (int)(radius * Math.sin(angle));
    
    // 添加随机偏移避免完全重叠
    x += random.nextInt(20) - 10;
    y += random.nextInt(20) - 10;
    
    nodes.add(new Node(i, String.valueOf(i), new Point(x, y)));
}

5. 反馈精准性

问题:添加 5 条边,其中 2 条是重复的,如何告知用户?

解决

java 复制代码
int successCount = 0;
int failCount = 0;

for (EdgeInfo edge : edges) {
    if (graph.addEdge(edge.from, edge.to, edge.weight)) {
        successCount++;
    } else {
        failCount++;
    }
}

// 精准反馈
if (successCount > 0 && failCount > 0) {
    message = String.format("✓ 成功添加 %d 条边,%d 条重复未添加", 
                            successCount, failCount);
} else if (successCount > 0) {
    message = "✓ 成功添加 " + successCount + " 条边";
} else {
    message = "✗ 所有边都已存在,未添加任何边";
}

🚀 快速开始

1. 环境准备

确保安装了 JDK 8 或更高版本

bash 复制代码
java -version
# 输出示例:java version "1.8.0_301"

2. 获取源码

bash 复制代码
git clone https://gitee.com/you-tanzhi/algo-viz-ai.git
cd algo-viz-ai

3. 编译运行

bash 复制代码
# 编译
javac -encoding UTF-8 *.java

# 运行
java Main

4. 开始使用

步骤1:选择"图结构可视化"选项卡

步骤2:在 AI 助手输入框输入:

复制代码
创建无向图,顶点A,B,C,D,E,边<A,B,10>、<B,C,15>、<C,D,20>、<D,E,25>、<A,E,30>

步骤3:点击"执行命令",自动生成图结构

步骤4:输入:

复制代码
运行Dijkstra算法,从A到E

步骤5:观看算法动画演示!


📚 支持的功能清单

图结构模块

功能 命令示例 说明
创建图 创建无向图,顶点1,2,3,边<1,2,10> 支持有向/无向
添加节点 添加节点5,6,7 批量添加
添加边 添加边<3,5,20>、<5,7,15> 支持权重
DFS 遍历 运行DFS算法,从节点0开始 深度优先
BFS 遍历 运行BFS算法,从节点1开始 广度优先
Prim MST 运行Prim算法 最小生成树
Kruskal MST 运行Kruskal算法 最小生成树
Dijkstra 运行Dijkstra算法,起点0,终点5 最短路径
查看存储 点击按钮 邻接矩阵/表
保存图 点击"保存"按钮 .graph 文件
加载图 点击"加载"按钮 加载已保存图
删除模式 点击"删除模式"按钮 删除节点/边

排序算法模块

算法 时间复杂度 空间复杂度 稳定性
直接插入排序 O(n²) O(1) 稳定
简单选择排序 O(n²) O(1) 不稳定
快速排序 O(nlogn) O(logn) 不稳定

🔧 技术细节深入

1. 如何实现平滑动画?

关键 :使用 javax.swing.Timer + repaint()

java 复制代码
// 错误做法:直接 sleep 会卡死 GUI
for (int i = 0; i < steps.size(); i++) {
    applyStep(steps.get(i));
    Thread.sleep(500);  // ❌ GUI 冻结!
    repaint();
}

// 正确做法:使用 Timer
Timer timer = new Timer(500, new ActionListener() {
    private int currentStep = 0;
    
    @Override
    public void actionPerformed(ActionEvent e) {
        if (currentStep < steps.size()) {
            applyStep(steps.get(currentStep));
            currentStep++;
            repaint();
        } else {
            ((Timer) e.getSource()).stop();
        }
    }
});
timer.start();

2. 如何绘制带箭头的有向边?

java 复制代码
private void drawArrow(Graphics2D g2d, int x1, int y1, 
                       int x2, int y2) {
    // 1. 绘制线段
    g2d.drawLine(x1, y1, x2, y2);
    
    // 2. 计算箭头方向
    double angle = Math.atan2(y2 - y1, x2 - x1);
    
    // 3. 箭头两侧点(30度夹角,长度15)
    int arrowSize = 15;
    double angle1 = angle + Math.toRadians(150);
    double angle2 = angle - Math.toRadians(150);
    
    int[] xPoints = {
        x2,
        x2 + (int)(arrowSize * Math.cos(angle1)),
        x2 + (int)(arrowSize * Math.cos(angle2))
    };
    int[] yPoints = {
        y2,
        y2 + (int)(arrowSize * Math.sin(angle1)),
        y2 + (int)(arrowSize * Math.sin(angle2))
    };
    
    // 4. 绘制箭头三角形
    g2d.fillPolygon(xPoints, yPoints, 3);
}

3. 如何处理节点拖拽?

java 复制代码
private Point dragStart;
private Node draggedNode;

@Override
public void mousePressed(MouseEvent e) {
    for (Node node : graph.getNodes()) {
        if (node.contains(e.getPoint())) {
            draggedNode = node;
            dragStart = e.getPoint();
            break;
        }
    }
}

@Override
public void mouseDragged(MouseEvent e) {
    if (draggedNode != null) {
        int dx = e.getX() - dragStart.x;
        int dy = e.getY() - dragStart.y;
        
        draggedNode.position.x += dx;
        draggedNode.position.y += dy;
        
        dragStart = e.getPoint();
        repaint();
    }
}

@Override
public void mouseReleased(MouseEvent e) {
    draggedNode = null;
}

💡 学习收获

通过这个项目,我深入学习了:

数据结构方面

  • ✅ 图的两种存储方式的优缺点
  • ✅ DFS、BFS、Dijkstra、Prim、Kruskal 算法的完整实现
  • ✅ 并查集在检测环路中的应用
  • ✅ 优先队列在贪心算法中的使用

编程技术方面

  • ✅ Java Swing GUI 编程的完整流程
  • ✅ MVC 架构在大型项目中的应用
  • ✅ 正则表达式的高级用法
  • ✅ 事件驱动编程的设计模式
  • ✅ Graphics2D 的高级绘图技术

工程实践方面

  • ✅ 模块化设计,降低代码耦合度
  • ✅ 异常处理和边界情况考虑
  • ✅ 用户体验优化(反馈精准、操作流畅)
  • ✅ 代码可维护性(注释、命名规范)

🎓 适用场景

1. 数据结构课程教学

  • 老师演示算法执行过程
  • 学生实验和验证算法

2. 算法竞赛准备

  • 快速验证算法正确性
  • 理解算法内部机制

3. 面试准备

  • 复习图算法和排序算法
  • 可视化帮助记忆

4. 项目实战练习

  • 学习 Java GUI 编程
  • 理解 MVC 架构设计
  • 练习正则表达式

🤝 参与贡献

欢迎提交 Issue 和 Pull Request!

如何贡献

  1. Fork 本仓库
  2. 创建特性分支git checkout -b feature/AmazingFeature
  3. 提交更改git commit -m 'Add some AmazingFeature'
  4. 推送分支git push origin feature/AmazingFeature
  5. 提交 Pull Request

代码规范

  • 遵循 Java 命名规范(驼峰命名)
  • 添加必要的注释
  • 确保编译无警告

📜 开源协议

本项目采用 MIT License 开源协议。

你可以自由地:

  • ✅ 使用、复制、修改代码
  • ✅ 用于商业或非商业项目
  • ✅ 分发和再授权

唯一要求:

  • 保留原作者版权声明

🙏 致谢

感谢以下资源和工具:

  • Java 官方文档:提供了 Swing 的详细 API
  • 《算法导论》:算法理论基础
  • StackOverflow 社区:解决了无数技术难题
  • Gitee 平台:提供了稳定的代码托管服务

📝 总结

这个项目历时 1 周 (根据实际情况填写),编写了 5000+ 行代码,实现了:

✅ 6 种核心图算法的完整可视化

✅ 3 种排序算法的动画演示

✅ 自然语言交互的 AI 助手

✅ 图结构的保存和加载

✅ 双重存储结构的实时展示

通过这个项目,我不仅掌握了数据结构和算法的底层原理 ,还学会了如何将抽象的算法转化为直观的可视化

希望这个项目能帮助到同样在学习数据结构的你!🎉


如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!

有任何问题欢迎在评论区留言或提交 Issue!


🏷️ 标签

#Java #Swing #数据结构 #算法可视化 #图算法 #排序算法 #Dijkstra #BFS #DFS #最小生成树 #GUI编程 #MVC架构 #自然语言处理 #教学工具 #开源项目

相关推荐
王嘉俊9252 小时前
设计模式--装饰器模式:动态扩展对象功能的优雅设计
java·设计模式·装饰器模式
ʚ希希ɞ ྀ2 小时前
二叉树的层序遍历
数据结构·算法
循着风3 小时前
多种二分查找
java
努力也学不会java3 小时前
【Java并发】深入理解synchronized
java·开发语言·人工智能·juc
TDengine (老段)3 小时前
TDengine 数学函数 CEIL 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
LB21123 小时前
Redis 黑马skyout
java·数据库·redis
Tiny番茄3 小时前
leetcode 3. 无重复字符的最长子串
数据结构·python·算法·leetcode
豐儀麟阁贵3 小时前
Java知识点储备
java·开发语言
hrrrrb3 小时前
【Spring Security】Spring Security 密码编辑器
java·hive·spring