/**
* 检查给定点是不是核心点
* @param lst 存放点的链表
* @param p 待测试的点
* @param e e半径
* @param minp 密度阈值
* @return 暂时存放访问过的点
*/
public static List isKeyPoint(List lst,Point p,int e,int minp){
int count=0;
List tmpLst=new ArrayList();
for(Iterator it=lst.iterator();it.hasNext();){
Point q=it.next();
if(getDistance(p,q)<=e){
++count;
if(!tmpLst.contains(q)){
tmpLst.add(q);
}
}
}
if(count>=minp){
p.setKey(true);
return tmpLst;
}
return null;
}
public static void setListClassed(List lst){
for(Iterator it=lst.iterator();it.hasNext();){
Point p=it.next();
if(!p.isClassed()){
p.setClassed(true);
}
}
}
/**
* 如果b中含有a中包含的元素,则把两个集合合并
* @param a
* @param b
* @return a
*/
public static boolean mergeList(List a,List b){
boolean merge=false;
for(int index=0;index
if(a.contains(b.get(index))){
merge=true;
break;
}
}
if(merge){
for(int index=0;index
if(!a.contains(b.get(index))){
a.add(b.get(index));
}
}
}
return merge;
}
/**
* 返回文本中的点集合
* @return 返回文本中点的集合
* @throws IOException
*/
public static List getPointsList() throws IOException{
List lst=new ArrayList();
String txtPath="src\\com\\sunzhenxing\\points.txt";
BufferedReader br=new BufferedReader(new FileReader(txtPath));
String str="";
while((str=br.readLine())!=null && str!=""){
lst.add(new Point(str));
}
br.close();
return lst;
}
}
最后在主程序中实现算法,如下所示:
package com.sunzhenxing;
import java.io.*;
import java.util.*;
public class Dbscan {
private static List pointsList=new ArrayList();//存储所有点的集合
private static List> resultList=new ArrayList>();//存储DBSCAN算法返回的结果集
private static int e=2;//e半径
private static int minp=3;//密度阈值
/**
* 提取文本中的的所有点并存储在pointsList中
* @throws IOException
*/
private static void display(){
int index=1;
for(Iterator> it=resultList.iterator();it.hasNext();){
List lst=it.next();
if(lst.isEmpty()){
continue;
}
System.out.println("-----第"+index+"个聚类-----");
for(Iterator it1=lst.iterator();it1.hasNext();){
Point p=it1.next();
System.out.println(p.print());
}
index++;
}
}
//找出所有可以直达的聚类
private static void applyDbscan(){
try {
pointsList=Utility.getPointsList();
for(Iterator it=pointsList.iterator();it.hasNext();){
Point p=it.next();
if(!p.isClassed()){
List tmpLst=new ArrayList();
if((tmpLst=Utility.isKeyPoint(pointsList, p, e, minp)) != null){
//为所有聚类完毕的点做标示
Utility.setListClassed(tmpLst);
resultList.add(tmpLst);
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//对所有可以直达的聚类进行合并,即找出间接可达的点并进行合并
private static List> getResult(){
applyDbscan();//找到所有直达的聚类
int length=resultList.size();
for(int i=0;i
for(int j=i+1;j
if(Utility.mergeList(resultList.get(i), resultList.get(j))){
resultList.get(j).clear();
}
}
}
return resultList;
}
/**
* 程序主函数
* @param args
*/
public static void main(String[] args) {
getResult();
display();
//System.out.println(Utility.getDistance(new Point(0,0), new Point(0,2)));
}
}
下边是一个小测试, 即使用src\\com\\sunzhenxing\\points.txt文件的内容进行测试,points.txt的文件内容是:
0,0
0,1
0,2
0,3
0,4
0,5
12,1
12,2
12,3
12,4
12,5
12,6
0,6
0,7
12,7
0,8
0,9
1,1
最后算法的结果是:
-----第1个聚类-----
<0,0>
<0,1>
<0,2>
<1,1>
<0,3>
<0,4>
<0,5>
<0,6>
<0,7>
<0,8>
<0,9>
-----第2个聚类-----
<12,1>
<12,2>
<12,3>
<12,4>
<12,5>
<12,6>
<12,7>
大家画一下坐标就可以理解实验的结论了。