基于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架构 #自然语言处理 #教学工具 #开源项目

相关推荐
永远有缘38 分钟前
Java、Python、C# 和 C++ 在函数定义语法上的主要区别
java·c++·python·c#
任风雨3 小时前
13.2.3.Tomcat
java·tomcat
10001hours4 小时前
初阶数据结构.1.顺序表.通讯录项目(只有源码和注释)
数据结构·算法
qq_336313936 小时前
java基础-字符串
java
二进制person7 小时前
Java EE初阶 --多线程2
java·开发语言
007php0078 小时前
某游戏大厂 Java 面试题深度解析(四)
java·开发语言·python·面试·职场和发展·golang·php
西西学代码9 小时前
Flutter---个人信息(5)---持久化存储
java·javascript·flutter
陈果然DeepVersion9 小时前
Java大厂面试真题:Spring Boot+Kafka+AI智能客服场景全流程解析(五)
java·spring boot·kafka·向量数据库·大厂面试·rag·ai智能客服
FAFU_kyp9 小时前
Spring Boot 邮件发送系统 - 从零到精通教程
java·网络·spring boot