K-means 算法是一种常见的聚类算法,以下是 Java 17 实现一维数据 K-means 算法的代码: ```java import java.util.ArrayList; import java.util.List; import java.util.Random; // KMeans 类用于执行一维数据的 K-means 聚类 class KMeans { private final int k; // 聚类的数量 private final int maxIterations; // 最大迭代次数 public KMeans(int k, int maxIterations) { this.k = k; this.maxIterations = maxIterations; } // 执行 K-means 聚类的主方法 public List<List<Double>> cluster(List<Double> data) { // 初始化质心 List<Double> centroids = initializeCentroids(data); List<List<Double>> clusters = null; for (int i = 0; i < maxIterations; i++) { // 根据当前质心分配数据点到各个聚类 clusters = assignClusters(data, centroids); // 更新质心 List<Double> newCentroids = updateCentroids(clusters); // 如果质心不再变化,停止迭代 if (centroids.equals(newCentroids)) { break; } centroids = newCentroids; } return clusters; } // 初始化质心,随机从数据中选择 k 个点作为初始质心 private List<Double> initializeCentroids(List<Double> data) { List<Double> centroids = new ArrayList<>(); Random random = new Random(); while (centroids.size() < k) { int index = random.nextInt(data.size()); double centroid = data.get(index); if (!centroids.contains(centroid)) { centroids.add(centroid); } } return centroids; } // 根据当前质心分配数据点到各个聚类 private List<List<Double>> assignClusters(List<Double> data, List<Double> centroids) { List<List<Double>> clusters = new ArrayList<>(); for (int i = 0; i < k; i++) { clusters.add(new ArrayList<>()); } for (double point : data) { int closestCentroidIndex = findClosestCentroid(point, centroids); clusters.get(closestCentroidIndex).add(point); } return clusters; } // 找到距离给定点最近的质心的索引 private int findClosestCentroid(double point, List<Double> centroids) { int closestIndex = 0; double minDistance = Double.MAX_VALUE; for (int i = 0; i < centroids.size(); i++) { double distance = Math.abs(point - centroids.get(i)); if (distance < minDistance) { minDistance = distance; closestIndex = i; } } return closestIndex; } // 更新质心,计算每个聚类的平均值作为新的质心 private List<Double> updateCentroids(List<List<Double>> clusters) { List<Double> newCentroids = new ArrayList<>(); for (List<Double> cluster : clusters) { if (cluster.isEmpty()) { newCentroids.add(0.0); } else { double sum = 0; for (double point : cluster) { sum += point; } newCentroids.add(sum / cluster.size()); } } return newCentroids; } } // 主类,用于测试 K-means 算法 public class KMeansOneDimensional { public static void main(String[] args) { // 一维数据 List<Double> data = List.of(1.0, 2.0, 3.0, 10.0, 11.0, 12.0, 20.0, 21.0, 22.0); int k = 3; // 聚类数量 int maxIterations = 100; // 最大迭代次数 KMeans kMeans = new KMeans(k, maxIterations); List<List<Double>> clusters = kMeans.cluster(data); // 输出聚类结果 for (int i = 0; i < clusters.size(); i++) { System.out.println("Cluster " + (i + 1) + ": " + clusters.get(i)); } } } ``` 代码说明: 1. KMeans 类:封装了 K-means 算法的核心逻辑,包括初始化质心、分配数据点到聚类、更新质心等方法。 2. initializeCentroids 方法:随机从数据中选择 `k` 个点作为初始质心。 3. assignClusters 方法:根据当前质心,将每个数据点分配到距离最近的质心所在的聚类。 4. updateCentroids 方法:计算每个聚类的平均值作为新的质心。 5. findClosestCentroid 方法:找到距离给定点最近的质心的索引。 6. KMeansOneDimensional 类:包含 `main` 方法,用于测试 K-means 算法。 额外需要注意的逻辑点: 1. 初始质心的选择:初始质心的选择会影响聚类结果,不同的初始质心可能导致不同的聚类结果。可以多次运行算法,选择最优的结果。 2. 空聚类的处理:在更新质心时,如果某个聚类为空,代码中简单地将其质心设为 0。在实际应用中,可能需要根据具体情况处理空聚类。 3. 最大迭代次数:设置最大迭代次数可以避免算法陷入无限循环。但如果最大迭代次数设置过小,可能导致算法提前终止,聚类结果不准确。 [2025-06-23 09:49:50 | AI写代码神器 | 1377点数解答]