1、以下图的样本数据为测试数据、不使用java自带的DBSCAN算法进行编写,自行从0开始实现此算法,由于时间紧迫,比较粗糙,100可得60、因代码有太多遍历样本集合以及还有类似递归的调用自身方法的方法,导致代码不够优美,要不是时间太少,肯定是容忍不了的,但同时也有一二优点,比如会下意识的使用解耦,将几个复杂模块分开,然后逐一解决、如图我使用两个方法,和一个main方法,其中hx。。。方法主要处理判断是否能成簇,如果能则返回成簇的集合(即成簇中点的集合),不能则返回null。这样方便main方法和big。。方法获取数据以及让代码看起来优雅一点,big。。方法则是不断判断核心圆中的点是否为核心圆,如果是又调用自身继续判断,直到此簇的所有点都遍历到,其余不做赘述。
以此为例:
得java代码:
package bigData;
import java.awt.*;
import java.util.Arrays;
// 思路:我们要将散落的点形成簇,就是寻找点与点之间的密度相连关系。
// 第一步:定义好点的集合,半径,以及最小的圈内点数和准备一个用来输出簇的集合
// 算法思路:
// 1、先遍历集合中的点获得一个核心点。和与之对应的核心圆、将每一个核心点标记,标记后的点可不参与重复的核心点判断
// 2、收集核心圆中的点(除核心点外),因为这些都能成为密度相连的点 存放在 c 集合。
// 3、将 c 集合中的点 看做核心点去判断能否成为核心点、能则重复步骤2,3.不能则代表此簇中的点全部找完,
// 4、继续遍历集合中的点,直至全部遍历,输出存在的簇。
public class Test01 {
public int[] B=new int[20]; // 存放密度相连的结果集合
public int ib=0; // 密度相连结果集合的下标
// 判断点能否成为簇、能返回簇,不能返回null
public Point[] hxPoint(int[][] A,double r,int a,Point point){
// 判断是否能成簇,能返回点集合,不能则返回null;
Point[] points = new Point[20]; // 存储能密度直达的点
int b=0;
for (int i=0;i<A.length;i++){
for (int j =0;j<A[i].length;j++){
if (A[i][j]>0){
if (i==point.x&&j!=point.y) {
if (Math.abs(point.y-j)<=r){
// 加一,且存入密度直达点的集合中
points[b] = new Point(i,j);
b++;
}
}else if (j==point.y&&i!=point.x) {
if (Math.abs(point.x - i) <= r) {
// 加一,且存入密度直达点的集合中
points[b] = new Point(i, j);
b++;
}
}else if (i==point.x&&j==point.y){
// 加一,且存入密度直达点的集合中
points[b] = new Point(i,j);
b++;
} else {
if ( Math.sqrt(Math.abs((point.x-i)*(point.x-i))+Math.abs((point.y-j)*(point.y-j)))<=r){
// 加一,且存入密度直达点的集合中
points[b] = new Point(i,j);
b++;
}
}
}
}
}
Point[] points1 = new Point[b]; // 存储能密度直达的点
for (int i=0;i<b;i++){
points1[i] = new Point(points[i].x,points[i].y);
}
if (b>=a) return points1;
return null;
}
// 判断哪些点能够密度相连
public void bigData(int[][] A,double r,int a,Point[] points,Point point1){
// 我们已知第一次的核心圆中所有点,则遍历点
for (Point point : points) {
// 不管是不是核心点都会记录成为密度相连的点
if ((A[point.x][point.y]>100)) {
B[ib++] = A[point.x][point.y];
}
// 判断点是否为核心点,若为,则继续调用此方法进行遍历,若不为,则放弃。
// 不管是不是都打上标记(即数值减100)表示后续可跳过此点
if (A[point.x][point.y] > 100) {
Point[] points1 = hxPoint(A, r, a, point);
if (points1 == null ) {
// 不为核心点,则标记点
A[point.x][point.y] = A[point.x][point.y] - 100;
} else if (points1 != null) {
//为核心点,即能成簇,且没被使用过,则将以此点为核心点的圆中点继续调用此方法,调用前标记点
// 直到遍历完所有点。
A[point.x][point.y] = A[point.x][point.y] - 100;
bigData(A, r, a, points1,point);
}
}
}
}
public static void main(String[] args) {
// 设定A集合的点12个、半径 1、成簇点 4
// 定义整型二维数组、以0,0为开始,如果坐标上有点则赋值为101、之后的点为102...,第一个1为标志位,1代表未访问。
int[][] A = new int[][]{ {0,0 ,0 ,0 ,0 ,0 ,0},
{0,0 ,101,0 ,0 ,102,0},
{0,103,104,105,106,107,108},
{0,109,110,0 ,0 ,111,0},
{0,0 ,112,0 ,0 ,0 ,0}};
double r = 1.0; int a = 4;int c=0;int d=1;
Test01 test01 = new Test01();
//先确定一个核心点
for (int i=0;i<A.length;i++) {
for (int j = 0; j < A[i].length; j++) {
// 依次遍历点,直到找核心点,就调用算法计算,计算完后还需继续遍历后续没有被标记的点
// 遍历的是有值的点
if (A[i][j] > 100) {
Point[] points = test01.hxPoint(A, r, a, new Point(i, j));
if (points != null) {
// 不管是不是核心点都会记录成为密度相连的点
test01.B[test01.ib++] = A[i][j];
// 且被标记
A[i][j] = A[i][j] - 100;
test01.bigData(A, r, a, points,new Point(i, j));
System.out.println("此时最终成簇"+(d++)+"的集合为:=======================\n");
System.out.print("(");
for (int n=c;n<test01.ib;n++) {
System.out.print(test01.B[n]+",");
}
System.out.println(")");
c=test01.ib;
}
}
}
}
System.out.println("A集合中的元素为:");
System.out.println(Arrays.toString(A[0]));
System.out.println(Arrays.toString(A[1]));
System.out.println(Arrays.toString(A[2]));
System.out.println(Arrays.toString(A[3]));
System.out.println(Arrays.toString(A[4]));
}
}
结果截图:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)