基于聚类分析算法的数字化图书馆、图书馆管理系统


本系统为大学生毕业设计程序,项目涉及技术为:springboot、mybatis、mysql、vue.js、javascript、html、k-means聚类算法、maven等等。

1.图书馆管理系统用户登录:

 

2.图书馆管理系统主页:

 

3.图书管理列表:

 

4.图书高级检索:

5.图书新增:

 

6.图书信息编辑:

 

7.用户借阅图书列表:

 

8.图书推荐排行榜:

 

k-means算法java实现

package com.bskf.modules.job.utils;

import java.util.ArrayList;
import java.util.List;

public class Kcluster {
    private int id;// 标识
    private Kpoint center;// 中心
    private List<Kpoint> members = new ArrayList<Kpoint>();// 成员

    public Kcluster(int id, Kpoint center) {
        this.id = id;
        this.center = center;
    }

    public Kcluster(int id, Kpoint center, List<Kpoint> members) {
        this.id = id;
        this.center = center;
        this.members = members;
    }

    public void addPoint(Kpoint newKpoint) {
        members.add(newKpoint);
    }

    public int getId() {
        return id;
    }

    public Kpoint getCenter() {
        return center;
    }

    public void setCenter(Kpoint center) {
        this.center = center;
    }

    public List<Kpoint> getMembers() {
        return members;
    }

    @Override
    public String toString() {
        String toString = "Kcluster \n" + "Cluster_id=" + this.id + ", center:{" + this.center.toString() + "}";
        for (Kpoint kpoint : members) {
            toString += "\n" + kpoint.toString();
        }
        return toString + "\n";
    }
}



package com.bskf.modules.job.utils;

import java.util.*;

public class KmeansRunner {

    private int kNum;                             //簇的个数
    private int iterNum = 10;                     //迭代次数
    private int iterMaxTimes = 100000;            //单次迭代最大运行次数
    private int iterRunTimes = 0;                 //单次迭代实际运行次数
    private float disDiff = (float) 0.01;         //单次迭代终止条件,两次运行中类中心的距离差
    private Map<Long, float[]> original_data;    //用于存放,原始数据集
    private static List<Kpoint> kpointList = null;   //用于存放,原始数据集所构建的点集
    private int len = 0;                           //用于记录每个数据点的维度

    public KmeansRunner(int k, Map<Long, float[]> original_data) {
        this.kNum = k;
        this.original_data = original_data;
        this.len = original_data.values().iterator().next().length;
        //检查规范
        check();
        //初始化点集。
        init();
    }

    /**
     * 检查规范
     */
    private void check() {
        if (kNum == 0) {
            throw new IllegalArgumentException("k must be the number > 0");
        }
        if (original_data == null) {
            throw new IllegalArgumentException("program can't get real data");
        }
    }

    /**
     * 初始化数据集,把数组转化为Point类型。
     */
    private void init() {
        kpointList = new ArrayList<>();
        for (Long uid : original_data.keySet()) {
            kpointList.add(new Kpoint(Math.toIntExact(uid), original_data.get(uid)));
        }
        System.out.println(kpointList);
    }

    /**
     * 随机选取中心点,构建成中心类。
     */
    private Set<Kcluster> chooseCenterCluster() {
        Set<Kcluster> kclusterSet = new HashSet<Kcluster>();
        Random random = new Random();
        for (int id = 0; id < kNum; ) {
            int anInt = random.nextInt(kpointList.size());
            Kpoint kpoint = kpointList.get(anInt);
            // 用于标记是否已经选择过该数据。
            boolean flag = true;
            for (Kcluster kcluster : kclusterSet) {
                if (kcluster.getCenter().equals(kpoint)) {
                    flag = false;
                }
            }
            // 如果随机选取的点没有被选中过,则生成一个cluster
            if (flag) {
                Kcluster kcluster = new Kcluster(id, kpoint);
                kclusterSet.add(kcluster);
                id++;
            }
        }
        return kclusterSet;
    }

    /**
     * 为每个点分配一个类!
     */
    public void cluster(Set<Kcluster> kclusterSet) {
        // 计算每个点到K个中心的距离,并且为每个点标记类别号
        for (Kpoint kpoint : kpointList) {
            float min_dis = Integer.MAX_VALUE;
            for (Kcluster kcluster : kclusterSet) {
                float tmp_dis = (float) Math.min(getEuclideanDis(kpoint, kcluster.getCenter()), min_dis);
                if (tmp_dis != min_dis) {
                    min_dis = tmp_dis;
                    kpoint.setClusterId(kcluster.getId());
                    kpoint.setDist(min_dis);
                }
            }
        }
        // 新清除原来所有的类中成员。把所有的点,分别加入每个类别
        for (Kcluster kcluster : kclusterSet) {
            kcluster.getMembers().clear();
            for (Kpoint kpoint : kpointList) {
                if (kpoint.getClusterid() == kcluster.getId()) {
                    kcluster.addPoint(kpoint);
                }
            }
        }
    }

    /**
     * 计算每个类的中心位置!
     */
    public boolean calculateCenter(Set<Kcluster> kclusterSet) {
        boolean ifNeedIter = false;
        for (Kcluster kcluster : kclusterSet) {
            List<Kpoint> kpoint_list = kcluster.getMembers();
            float[] sumAll = new float[len];
            // 所有点,对应各个维度进行求和
            for (int i = 0; i < len; i++) {
                for (int j = 0; j < kpoint_list.size(); j++) {
                    sumAll[i] += kpoint_list.get(j).getlocalArray()[i];
                }
            }
            // 计算平均值
            for (int i = 0; i < sumAll.length; i++) {
                sumAll[i] = (float) sumAll[i] / kpoint_list.size();
            }
            // 计算两个新、旧中心的距离,如果任意一个类中心移动的距离大于dis_diff则继续迭代。
            if (getEuclideanDis(kcluster.getCenter(), new Kpoint(sumAll)) > disDiff) {
                ifNeedIter = true;
            }
            // 设置新的类中心位置
            kcluster.setCenter(new Kpoint(sumAll));
        }
        return ifNeedIter;
    }

    /**
     * 运行 k-means
     */
    public Set<Kcluster> run() {
        Set<Kcluster> kclusterSet = chooseCenterCluster();
        boolean ifNeedIter = true;
        while (ifNeedIter) {
            cluster(kclusterSet);
            ifNeedIter = calculateCenter(kclusterSet);
            iterRunTimes++;
        }
        return kclusterSet;
    }

    /**
     * 返回实际运行次数
     */
    public int getIterTimes() {
        return iterRunTimes;
    }


    /**
     * 求欧式距离
     */
    public static double getEuclideanDis(Kpoint p1, Kpoint p2) {
        double count_dis = 0;
        float[] p1_local_array = p1.getlocalArray();
        float[] p2_local_array = p2.getlocalArray();

        if (p1_local_array.length != p2_local_array.length) {
            throw new IllegalArgumentException("length of array must be equal!");
        }

        for (int i = 0; i < p1_local_array.length; i++) {
            count_dis += Math.pow(p1_local_array[i] - p2_local_array[i], 2);
        }

        return Math.sqrt(count_dis);
    }
}

package com.bskf.modules.job.utils;
public class Kpoint {
    private float[] localArray;
    private int id;
    private int clusterId;  // 标识属于哪个类中心。
    private float dist;     // 标识和所属类中心的距离。

    public Kpoint(int id, float[] localArray) {
        this.id = id;
        this.localArray = localArray;
    }

    public Kpoint(float[] localArray) {
        this.id = -1; //表示不属于任意一个类
        this.localArray = localArray;
    }

    public float[] getlocalArray() {
        return localArray;
    }

    public int getId() {
        return id;
    }

    public void setClusterId(int clusterId) {
        this.clusterId = clusterId;
    }

    public int getClusterid() {
        return clusterId;
    }

    public float getDist() {
        return dist;
    }

    public void setDist(float dist) {
        this.dist = dist;
    }

    @Override
    public String toString() {
        String result = "Point_id=" + id + "  [";
        for (int i = 0; i < localArray.length; i++) {
            result += localArray[i] + " ";
        }
        return result.trim() + "] clusterId: " + clusterId + " dist: " + dist;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || getClass() != obj.getClass())
            return false;

        Kpoint kpoint = (Kpoint) obj;
        if (kpoint.localArray.length != localArray.length)
            return false;

        for (int i = 0; i < localArray.length; i++) {
            if (Float.compare(kpoint.localArray[i], localArray[i]) != 0) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        float x = localArray[0];
        float y = localArray[localArray.length - 1];
        long temp = x != +0.0d ? Double.doubleToLongBits(x) : 0L;
        int result = (int) (temp ^ (temp >>> 32));
        temp = y != +0.0d ? Double.doubleToLongBits(y) : 0L;
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

}

代码太多了,就不详细列举了,有需要的可以联系我,拿代码。。。

Logo

快速构建 Web 应用程序

更多推荐