🚀 基于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;
}
        可视化效果:
- 从起点开始,节点逐个变绿(已访问)
 - 每次松弛边时,边变红闪烁
 - 最终路径用粗红线标出
 - 右侧显示 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!
如何贡献
- Fork 本仓库
 - 创建特性分支 :
git checkout -b feature/AmazingFeature - 提交更改 :
git commit -m 'Add some AmazingFeature' - 推送分支 :
git push origin feature/AmazingFeature - 提交 Pull Request
 
代码规范
- 遵循 Java 命名规范(驼峰命名)
 - 添加必要的注释
 - 确保编译无警告
 
📜 开源协议
本项目采用 MIT License 开源协议。
你可以自由地:
- ✅ 使用、复制、修改代码
 - ✅ 用于商业或非商业项目
 - ✅ 分发和再授权
 
唯一要求:
- 保留原作者版权声明
 
🙏 致谢
感谢以下资源和工具:
- Java 官方文档:提供了 Swing 的详细 API
 - 《算法导论》:算法理论基础
 - StackOverflow 社区:解决了无数技术难题
 - Gitee 平台:提供了稳定的代码托管服务
 
📝 总结
这个项目历时 1 周 (根据实际情况填写),编写了 5000+ 行代码,实现了:
✅ 6 种核心图算法的完整可视化
✅ 3 种排序算法的动画演示
✅ 自然语言交互的 AI 助手
✅ 图结构的保存和加载
✅ 双重存储结构的实时展示
通过这个项目,我不仅掌握了数据结构和算法的底层原理 ,还学会了如何将抽象的算法转化为直观的可视化。
希望这个项目能帮助到同样在学习数据结构的你!🎉
如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!
有任何问题欢迎在评论区留言或提交 Issue!
🏷️ 标签
#Java #Swing #数据结构 #算法可视化 #图算法 #排序算法 #Dijkstra #BFS #DFS #最小生成树 #GUI编程 #MVC架构 #自然语言处理 #教学工具 #开源项目