首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java版数据结构和算法+AI算法和技能:从基础数据结构到神经网络的全栈实现

Java版数据结构和算法+AI算法和技能:从基础数据结构到神经网络的全栈实现

原创
作者头像
用户12608867
发布2026-08-11 13:53:44
发布2026-08-11 13:53:44
1400
举报

Java版数据结构和算法+AI算法和技能:从基础数据结构到神经网络的全栈实现

一、引言

数据结构与算法是计算机科学的基石,而人工智能算法的实现同样离不开高效的数据结构支撑。在Java生态中,无论是构建机器学习模型还是实现深度学习推理,底层都依赖于精心设计的数据结构与算法。本文将从基础数据结构出发,逐步深入到AI算法的Java实现,涵盖线性回归、决策树、XGBoost与神经网络,提供完整的可运行代码示例。

二、数据结构与算法的核心关系

数据结构是载体,算法是方法论。数据结构研究数据的逻辑结构、物理结构以及它们之间的相互关系,并对这种结构定义相应的运算,设计出相应的算法。算法必须依赖数据结构这种载体,否则就是空谈。

2.1 时间复杂度分析

算法的评价标准是“快”和“省”——时间复杂度和空间复杂度。时间复杂度用大O表示法描述,常见的有:

  • O(1)常数阶:执行时间固定,与数据规模无关
  • O(n)线性阶:执行时间随数据规模线性增长
  • O(log n)对数阶:典型如二分查找
  • O(n log n)线性对数阶:如归并排序、快速排序
  • O(n²)平方阶:如冒泡排序

三、核心数据结构的Java实现

3.1 链表(LinkedList)

链表是最基础的动态数据结构之一,由节点组成,每个节点包含数据和指向下一个节点的引用。

代码语言:javascript
复制
public class ListNode<T> {
    T val;
    ListNode<T> next;
    
    public ListNode(T val) {
        this.val = val;
    }
}

public class LinkedList<T> {
    private ListNode<T> head;
    private int size;
    
    // 头插法
    public void addFirst(T val) {
        ListNode<T> newNode = new ListNode<>(val);
        newNode.next = head;
        head = newNode;
        size++;
    }
    
    // 尾插法
    public void addLast(T val) {
        ListNode<T> newNode = new ListNode<>(val);
        if (head == null) {
            head = newNode;
        } else {
            ListNode<T> cur = head;
            while (cur.next != null) {
                cur = cur.next;
            }
            cur.next = newNode;
        }
        size++;
    }
    
    // 反转链表(迭代法)—— O(n)时间复杂度
    public void reverse() {
        ListNode<T> prev = null;
        ListNode<T> cur = head;
        while (cur != null) {
            ListNode<T> next = cur.next;
            cur.next = prev;
            prev = cur;
            cur = next;
        }
        head = prev;
    }
}

3.2 二叉搜索树(BST)

二叉搜索树是AI算法中决策树、随机森林等模型的基础数据结构。

代码语言:javascript
复制
public class BST<K extends Comparable<K>, V> {
    private Node root;
    
    private class Node {
        K key;
        V value;
        Node left, right;
        int size;
        
        Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.size = 1;
        }
    }
    
    // 插入——O(log n)平均时间复杂度
    public void put(K key, V value) {
        root = put(root, key, value);
    }
    
    private Node put(Node node, K key, V value) {
        if (node == null) return new Node(key, value);
        int cmp = key.compareTo(node.key);
        if (cmp < 0) node.left = put(node.left, key, value);
        else if (cmp > 0) node.right = put(node.right, key, value);
        else node.value = value;
        node.size = 1 + size(node.left) + size(node.right);
        return node;
    }
    
    // 查找——O(log n)平均时间复杂度
    public V get(K key) {
        Node node = get(root, key);
        return node == null ? null : node.value;
    }
    
    private Node get(Node node, K key) {
        if (node == null) return null;
        int cmp = key.compareTo(node.key);
        if (cmp < 0) return get(node.left, key);
        else if (cmp > 0) return get(node.right, key);
        else return node;
    }
    
    private int size(Node node) {
        return node == null ? 0 : node.size;
    }
}

3.3 红黑树(Red-Black Tree)

红黑树是一种自平衡二叉搜索树,在Java的TreeMapTreeSet以及AI算法中的区间查询场景有广泛应用。

代码语言:javascript
复制
public class RedBlackTree<K extends Comparable<K>, V> {
    private static final boolean RED = true;
    private static final boolean BLACK = false;
    
    private class Node {
        K key;
        V value;
        Node left, right;
        boolean color;
        
        Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.color = RED; // 新节点默认为红色
        }
    }
    
    private Node root;
    
    // 左旋
    private Node rotateLeft(Node h) {
        Node x = h.right;
        h.right = x.left;
        x.left = h;
        x.color = h.color;
        h.color = RED;
        return x;
    }
    
    // 右旋
    private Node rotateRight(Node h) {
        Node x = h.left;
        h.left = x.right;
        x.right = h;
        x.color = h.color;
        h.color = RED;
        return x;
    }
    
    // 颜色翻转
    private void flipColors(Node h) {
        h.color = RED;
        h.left.color = BLACK;
        h.right.color = BLACK;
    }
    
    // 插入操作——保证红黑树平衡
    public void put(K key, V value) {
        root = put(root, key, value);
        root.color = BLACK;
    }
    
    private Node put(Node h, K key, V value) {
        if (h == null) return new Node(key, value);
        int cmp = key.compareTo(h.key);
        if (cmp < 0) h.left = put(h.left, key, value);
        else if (cmp > 0) h.right = put(h.right, key, value);
        else h.value = value;
        
        // 修复红黑树性质
        if (isRed(h.right) && !isRed(h.left)) h = rotateLeft(h);
        if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h);
        if (isRed(h.left) && isRed(h.right)) flipColors(h);
        
        return h;
    }
    
    private boolean isRed(Node x) {
        return x != null && x.color == RED;
    }
}

四、AI算法的Java实现

4.1 线性回归(Linear Regression)

线性回归是AI算法中最基础的模型,通过拟合一条直线最小化预测值与实际值之间的误差平方和,数学模型为 y = mx + b。

代码语言:javascript
复制
import Jama.Matrix;

public class LinearRegression {
    private double[] coefficients;
    
    // 添加偏置项(特征矩阵中插入全1列)
    private double[][] addIntercept(double[][] X) {
        int nSamples = X.length;
        int nFeatures = X[0].length;
        double[][] XWithIntercept = new double[nSamples][nFeatures + 1];
        for (int i = 0; i < nSamples; i++) {
            XWithIntercept[i][0] = 1; // 偏置项
            System.arraycopy(X[i], 0, XWithIntercept[i], 1, nFeatures);
        }
        return XWithIntercept;
    }
    
    // 最小二乘法计算系数:θ = (XᵀX)⁻¹Xᵀy
    private double[] calculateCoefficients(double[][] X, double[] y) {
        int nFeatures = X[0].length;
        double[][] XtX = new double[nFeatures][nFeatures];
        double[] XtY = new double[nFeatures];
        
        // 计算 XᵀX 和 Xᵀy
        for (int i = 0; i < X.length; i++) {
            for (int j = 0; j < nFeatures; j++) {
                for (int k = 0; k < nFeatures; k++) {
                    XtX[j][k] += X[i][j] * X[i][k];
                }
                XtY[j] += X[i][j] * y[i];
            }
        }
        
        return solveLinearEquation(XtX, XtY);
    }
    
    // 使用Jama库求解线性方程组
    private double[] solveLinearEquation(double[][] A, double[] b) {
        Matrix matrixA = new Matrix(A);
        Matrix matrixB = new Matrix(b, b.length);
        Matrix solution = matrixA.solve(matrixB);
        return solution.getColumnPackedCopy();
    }
    
    // 训练模型
    public void fit(double[][] X, double[] y) {
        double[][] XWithIntercept = addIntercept(X);
        this.coefficients = calculateCoefficients(XWithIntercept, y);
    }
    
    // 预测
    public double predict(double[] x) {
        double[] xWithIntercept = new double[x.length + 1];
        xWithIntercept[0] = 1;
        System.arraycopy(x, 0, xWithIntercept, 1, x.length);
        
        double prediction = 0;
        for (int i = 0; i < coefficients.length; i++) {
            prediction += coefficients[i] * xWithIntercept[i];
        }
        return prediction;
    }
    
    // 评估:均方误差(MSE)
    public double meanSquaredError(double[][] X, double[] y) {
        double sum = 0;
        for (int i = 0; i < X.length; i++) {
            double pred = predict(X[i]);
            sum += Math.pow(pred - y[i], 2);
        }
        return sum / X.length;
    }
}

4.2 决策树(Decision Tree)

决策树是一种白盒模型,通过一系列“如果-那么”的问题层层剖析问题,具有极强的可解释性。

代码语言:javascript
复制
import java.util.*;

class TreeNode {
    int splitFeature;      // 分裂特征索引
    double splitValue;     // 分裂阈值
    TreeNode left;         // 左子树
    TreeNode right;        // 右子树
    int label;             // 叶节点存储的类别
}

public class DecisionTree {
    private TreeNode root;
    private int maxDepth = 10;
    private int minSamplesSplit = 2;
    
    // 递归构建决策树
    public TreeNode buildTree(double[][] data, int[] labels, int depth) {
        if (shouldStop(data, labels, depth)) {
            return new TreeNode(mostCommonLabel(labels));
        }
        
        SplitInfo bestSplit = findBestSplit(data, labels);
        TreeNode node = new TreeNode();
        node.splitFeature = bestSplit.featureIndex;
        node.splitValue = bestSplit.threshold;
        
        // 递归分裂左右子树
        double[][] leftData = bestSplit.leftData;
        double[][] rightData = bestSplit.rightData;
        int[] leftLabels = bestSplit.leftLabels;
        int[] rightLabels = bestSplit.rightLabels;
        
        node.left = buildTree(leftData, leftLabels, depth + 1);
        node.right = buildTree(rightData, rightLabels, depth + 1);
        return node;
    }
    
    private boolean shouldStop(double[][] data, int[] labels, int depth) {
        if (depth >= maxDepth) return true;
        if (data.length < minSamplesSplit) return true;
        // 检查是否所有标签相同
        int firstLabel = labels[0];
        for (int label : labels) {
            if (label != firstLabel) return false;
        }
        return true;
    }
    
    private int mostCommonLabel(int[] labels) {
        Map<Integer, Integer> counts = new HashMap<>();
        for (int label : labels) {
            counts.put(label, counts.getOrDefault(label, 0) + 1);
        }
        int maxCount = 0;
        int mostCommon = labels[0];
        for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
            if (entry.getValue() > maxCount) {
                maxCount = entry.getValue();
                mostCommon = entry.getKey();
            }
        }
        return mostCommon;
    }
    
    // 计算基尼系数
    private double giniImpurity(int[] labels) {
        Map<Integer, Integer> counts = new HashMap<>();
        for (int label : labels) {
            counts.put(label, counts.getOrDefault(label, 0) + 1);
        }
        double impurity = 1.0;
        for (int count : counts.values()) {
            double prob = (double) count / labels.length;
            impurity -= prob * prob;
        }
        return impurity;
    }
    
    // 寻找最佳分裂点(最小化基尼系数)
    private SplitInfo findBestSplit(double[][] data, int[] labels) {
        int nFeatures = data[0].length;
        double bestGini = Double.MAX_VALUE;
        SplitInfo bestSplit = null;
        
        for (int feature = 0; feature < nFeatures; feature++) {
            // 对当前特征的所有取值排序
            List<Integer> indices = new ArrayList<>();
            for (int i = 0; i < data.length; i++) {
                indices.add(i);
            }
            indices.sort((a, b) -> Double.compare(data[a][feature], data[b][feature]));
            
            // 尝试每个可能的分裂阈值
            for (int i = 0; i < indices.size() - 1; i++) {
                int idx1 = indices.get(i);
                int idx2 = indices.get(i + 1);
                if (data[idx1][feature] == data[idx2][feature]) continue;
                
                double threshold = (data[idx1][feature] + data[idx2][feature]) / 2;
                
                // 分割数据
                List<double[]> leftDataList = new ArrayList<>();
                List<double[]> rightDataList = new ArrayList<>();
                List<Integer> leftLabelList = new ArrayList<>();
                List<Integer> rightLabelList = new ArrayList<>();
                
                for (int j = 0; j < data.length; j++) {
                    if (data[j][feature] <= threshold) {
                        leftDataList.add(data[j]);
                        leftLabelList.add(labels[j]);
                    } else {
                        rightDataList.add(data[j]);
                        rightLabelList.add(labels[j]);
                    }
                }
                
                if (leftLabelList.isEmpty() || rightLabelList.isEmpty()) continue;
                
                // 计算加权基尼系数
                double leftGini = giniImpurity(leftLabelList.stream().mapToInt(Integer::intValue).toArray());
                double rightGini = giniImpurity(rightLabelList.stream().mapToInt(Integer::intValue).toArray());
                double weightedGini = (leftLabelList.size() * leftGini + rightLabelList.size() * rightGini) / data.length;
                
                if (weightedGini < bestGini) {
                    bestGini = weightedGini;
                    bestSplit = new SplitInfo();
                    bestSplit.featureIndex = feature;
                    bestSplit.threshold = threshold;
                    bestSplit.leftData = leftDataList.toArray(new double[0][]);
                    bestSplit.rightData = rightDataList.toArray(new double[0][]);
                    bestSplit.leftLabels = leftLabelList.stream().mapToInt(Integer::intValue).toArray();
                    bestSplit.rightLabels = rightLabelList.stream().mapToInt(Integer::intValue).toArray();
                }
            }
        }
        return bestSplit;
    }
    
    // 预测
    public int predict(TreeNode node, double[] sample) {
        if (node.left == null && node.right == null) {
            return node.label;
        }
        if (sample[node.splitFeature] <= node.splitValue) {
            return predict(node.left, sample);
        } else {
            return predict(node.right, sample);
        }
    }
    
    // 训练入口
    public void fit(double[][] data, int[] labels) {
        this.root = buildTree(data, labels, 0);
    }
    
    // 预测入口
    public int predict(double[] sample) {
        return predict(root, sample);
    }
    
    private static class SplitInfo {
        int featureIndex;
        double threshold;
        double[][] leftData;
        double[][] rightData;
        int[] leftLabels;
        int[] rightLabels;
    }
}

决策树的训练时间复杂度为 O(n_features × n_samples × log n_samples),预测时间复杂度为 O(tree_depth)

4.3 XGBoost的核心思想与Java集成

XGBoost是GBDT算法的极致优化实现,核心思想是不断地添加树,每次添加一棵树去拟合上次预测的残差。XGBoost的目标函数包含损失函数和正则项:

代码语言:javascript
复制
Obj = Σ L(yi, ŷi) + Σ Ω(fk)

其中Ω(fk)为正则项,控制模型复杂度防止过拟合。

Java中集成XGBoost的Maven依赖:

代码语言:javascript
复制
<dependency>
    <groupId>ml.dmlc</groupId>
    <artifactId>xgboost4j</artifactId>
    <version>1.7.5</version>
</dependency>

代码语言:javascript
复制
import ml.dmlc.xgboost4j.java.Booster;
import ml.dmlc.xgboost4j.java.DMatrix;
import ml.dmlc.xgboost4j.java.XGBoost;
import ml.dmlc.xgboost4j.java.XGBoostError;

import java.util.HashMap;
import java.util.Map;

public class XGBoostExample {
    public static void main(String[] args) throws XGBoostError {
        // 准备训练数据
        float[][] trainData = {{1.0f, 2.0f}, {2.0f, 3.0f}, {3.0f, 4.0f}};
        float[] trainLabels = {0, 1, 0};
        
        DMatrix trainMat = new DMatrix(trainData, trainLabels);
        
        // 设置参数
        Map<String, Object> params = new HashMap<>();
        params.put("eta", 0.3);           // 学习率
        params.put("max_depth", 6);        // 最大深度
        params.put("objective", "binary:logistic");
        params.put("eval_metric", "logloss");
        
        // 训练模型
        Booster booster = XGBoost.train(trainMat, params, 100);
        
        // 预测
        float[][] testData = {{1.5f, 2.5f}};
        DMatrix testMat = new DMatrix(testData);
        float[][] predictions = booster.predict(testMat);
        
        // 保存模型
        booster.saveModel("xgboost_model.json");
    }
}

4.4 神经网络(Neural Network)的Java实现

使用Deeplearning4j(DL4J)构建和训练神经网络。

Maven依赖:

代码语言:javascript
复制
<dependency>
    <groupId>org.deeplearning4j</groupId>
    <artifactId>deeplearning4j-core</artifactId>
    <version>1.0.0-M2.1</version>
</dependency>
<dependency>
    <groupId>org.nd4j</groupId>
    <artifactId>nd4j-native-platform</artifactId>
    <version>1.0.0-M2.1</version>
</dependency>

代码语言:javascript
复制
import org.deeplearning4j.datasets.iterator.impl.MnistDataSetIterator;
import org.deeplearning4j.nn.api.OptimizationAlgorithm;
import org.deeplearning4j.nn.conf.MultiLayerConfiguration;
import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
import org.deeplearning4j.nn.conf.layers.DenseLayer;
import org.deeplearning4j.nn.conf.layers.OutputLayer;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.deeplearning4j.optimize.listeners.ScoreIterationListener;
import org.nd4j.evaluation.classification.Evaluation;
import org.nd4j.linalg.activations.Activation;
import org.nd4j.linalg.dataset.api.iterator.DataSetIterator;
import org.nd4j.linalg.learning.config.Adam;
import org.nd4j.linalg.lossfunctions.LossFunctions;

public class NeuralNetworkExample {
    public static void main(String[] args) throws Exception {
        // 1. 加载MNIST数据集
        DataSetIterator trainIter = new MnistDataSetIterator(64, true, 12345);
        DataSetIterator testIter = new MnistDataSetIterator(64, false, 12345);
        
        // 2. 构建网络配置
        MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
            .seed(12345)
            .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
            .updater(new Adam(0.001))
            .list()
            .layer(0, new DenseLayer.Builder()
                .nIn(784)   // MNIST: 28x28 = 784
                .nOut(256)
                .activation(Activation.RELU)
                .build())
            .layer(1, new DenseLayer.Builder()
                .nIn(256)
                .nOut(128)
                .activation(Activation.RELU)
                .build())
            .layer(2, new OutputLayer.Builder()
                .nIn(128)
                .nOut(10)   // 10个数字类别
                .activation(Activation.SOFTMAX)
                .lossFunction(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                .build())
            .build();
        
        // 3. 初始化模型
        MultiLayerNetwork model = new MultiLayerNetwork(conf);
        model.init();
        model.setListeners(new ScoreIterationListener(100));
        
        // 4. 训练
        System.out.println("开始训练...");
        for (int epoch = 0; epoch < 10; epoch++) {
            model.fit(trainIter);
            trainIter.reset();
            System.out.println("Epoch " + (epoch + 1) + " 完成");
        }
        
        // 5. 评估
        Evaluation eval = new Evaluation(10);
        while (testIter.hasNext()) {
            var ds = testIter.next();
            var output = model.output(ds.getFeatures());
            eval.eval(ds.getLabels(), output);
        }
        System.out.println(eval.stats());
    }
}

五、综合应用:基于数据结构的AI特征工程

在实际AI项目中,高效的数据结构选择直接影响模型性能。以下是一个完整的特征工程流水线示例:

代码语言:javascript
复制
import java.util.*;
import java.util.stream.Collectors;

public class FeatureEngineeringPipeline {
    
    // 使用HashMap进行高效的特征索引
    private Map<String, Integer> featureIndex = new HashMap<>();
    
    // 使用TreeMap进行有序特征存储(O(log n)插入与查找)
    private TreeMap<String, Double> featureCache = new TreeMap<>();
    
    // 使用红黑树维护特征重要性排序
    private RedBlackTree<String, Double> featureImportance = new RedBlackTree<>();
    
    // 特征归一化(Min-Max Scaling)
    public double[] normalize(double[] features, double[] min, double[] max) {
        double[] normalized = new double[features.length];
        for (int i = 0; i < features.length; i++) {
            if (max[i] - min[i] != 0) {
                normalized[i] = (features[i] - min[i]) / (max[i] - min[i]);
            }
        }
        return normalized;
    }
    
    // 使用二叉搜索树进行快速KNN查询
    public List<Integer> knnSearch(BST<Double, Integer> index, double[] query, int k) {
        // 在实际实现中,可使用KD-Tree或Ball-Tree优化
        // 此处展示数据结构在AI中的应用思路
        PriorityQueue<Map.Entry<Double, Integer>> pq = new PriorityQueue<>(
            (a, b) -> Double.compare(b.getKey(), a.getKey())
        );
        // 遍历BST进行最近邻搜索...
        return new ArrayList<>();
    }
    
    // 特征选择:基于信息增益
    public Set<String> selectFeatures(Map<String, double[]> features, 
                                       int[] labels, double threshold) {
        Set<String> selected = new HashSet<>();
        DecisionTree dt = new DecisionTree();
        // 使用决策树的信息增益进行特征选择
        // ...
        return selected;
    }
}

六、性能对比与优化策略

数据结构/算法

插入时间复杂度

查找时间复杂度

空间复杂度

AI应用场景

数组

O(1)

O(n)

O(n)

特征向量存储

链表

O(1)

O(n)

O(n)

动态特征序列

二叉搜索树

O(log n)

O(log n)

O(n)

特征索引

红黑树

O(log n)

O(log n)

O(n)

TreeMap实现

哈希表

O(1)

O(1)

O(n)

特征字典

跳表

O(log n)

O(log n)

O(n log n)

向量检索

七、总结

本文从Java数据结构的底层实现出发,逐步深入到AI算法的工程实践,涵盖了:

  1. 核心数据结构:链表、二叉搜索树、红黑树的完整Java实现
  2. 基础AI算法:线性回归(最小二乘法)、决策树(基尼系数分裂)的纯Java实现
  3. 工业级AI框架集成:XGBoost和Deeplearning4j的实际应用
  4. 特征工程:数据结构在AI特征处理中的优化应用

数据结构与算法是AI工程的基石——数据结构为算法服务,算法作用在数据结构之上。掌握这些核心实现,不仅能写出更高效的AI代码,更能深入理解AI框架的底层原理。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • Java版数据结构和算法+AI算法和技能:从基础数据结构到神经网络的全栈实现
    • 一、引言
    • 二、数据结构与算法的核心关系
      • 2.1 时间复杂度分析
    • 三、核心数据结构的Java实现
      • 3.1 链表(LinkedList)
      • 3.2 二叉搜索树(BST)
      • 3.3 红黑树(Red-Black Tree)
    • 四、AI算法的Java实现
      • 4.1 线性回归(Linear Regression)
      • 4.2 决策树(Decision Tree)
      • 4.3 XGBoost的核心思想与Java集成
      • 4.4 神经网络(Neural Network)的Java实现
    • 五、综合应用:基于数据结构的AI特征工程
    • 六、性能对比与优化策略
    • 七、总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档