求集合所有K划分的算法

在准备一篇论文的过程中,需要将一个集合进行k划分,并求出所有划分,网上搜了下并没有直接可用的算法,只好自己动手,特分享出来,转载请注明出处。

首先分析将包含n个元素的集合进行k划分,假定总的划分次数为F(n,k),则其所有的划分可以由kF(n-1,k)和F(n-1,k-1)得到,前者是指将集合的前n-1个元素划分成k个子集,则将第k个元素可以加入其中的任一个子集形成一个新的划分,后者是指集合的前n-1个元素划分成k-1个子集,则第k个元素作为一个单独的元素组成一个子集形成k划分,基于动态规划算法,建立二维矩阵subsets[n][k]保存所有划分。

随着k的增加,所有划分的集合空间迅速增大,需要找到一种高效的划分表示方法,我使用了一种称为“restricted growthfunction”的方法表示,对于大小为4的集合,RG=[0,0,0,0]表示集合划分{1,2,3,4} , RG=[0,1,1,0]表示{1,4},{2,3},具体见网页: http://delphiforfun.org/programs/Math_Topics/set_partitions.htm

实现的java代码如下:

import java.util.Random;
import java.lang.String;
import java.util.*;

public class cmf {

public static void main(String[] args) {

int[] n = new int[5];
for (int i = 0; i < n.length; i++){
n[i] = i+1;//(int) (Math.random()*100);
}
System.out.print("The sequence:");         
for(int i = 0; i < n.length; ++i){
System.out.print(n[i]+" ");
}
System.out.println("");
//      BigInteger l =getLCM(n);      
//      System.out.println("Their LCM is " +l.toString());

int maxk = 3;
int k = 0;
ArrayList[][] subsets = new ArrayList[n.length][maxk];
for (int i = 0; i < n.length; i++){
//free the unuseful objects to JVM 
if(i > 2)
for(int x = 0; x < maxk; x++){
subsets[i-2][x] =null;            
}

for(int j = 0; j < maxk; j++){
if(i >= j){
subsets[i][j] = newArrayList<int[]>();
}    
if(j == 0){
int[] s = new int[i+1];
for(k = 0; k < i+1; k++){
s[k] = 0;
}               
subsets[i][j].add(s);
}
else if(i == j){
int[] s = new int[i+1];
int rgstart = 0;
for(k = 0; k < i+1; k++){
s[k] = rgstart++;
}
subsets[i][j].add(s);            
}
else if ( i >j){               
ArrayList p = subsets[i-1][j];
for (k=0; k < p.size(); k++){
int[] aboveRG = (int[]) p.get(k);
int setsize = getMax(aboveRG);
for(int l = 0; l <= setsize; l++){
int[] s = new int[aboveRG.length+1];
for(int m = 0; m < aboveRG.length; m++)
s[m]=aboveRG[m];
s[aboveRG.length] = l;

subsets[i][j].add(s);
}
}
p =  subsets[i-1][j-1];
for (k=0; k < p.size(); k++){
int[] aboveRG = (int[]) p.get(k);
int[] s = new int[aboveRG.length+1];
for(int m = 0; m < aboveRG.length; m++)
s[m]=aboveRG[m];
s[aboveRG.length] = getMax(aboveRG)+1;
subsets[i][j].add(s);                                
}
}
if(i >= j)
System.out.println(""+(i+1)+","+(j+1)+""+subsets[i][j].size());
}
}
ArrayList p = subsets[n.length-1][maxk-1];

//    for (inti=0; i < p.size(); i++){
//      int[] setRG = (int[]) p.get(i);
//System.out.println(setRG.toString());
//   System.out.println(readPartition(setRG,n));
//}
System.out.println("Total number: "+p.size()+""+maxk+"-partitions");

}

public static String readPartition(int[] setRG, int[] n)
{
String ret = "";
int setsize = getMax(setRG);
for(int j =0; j <= setsize; j++){
for(int i = 0; i < setRG.length; i++){
//      System.out.print(""+setRG[i]);
if(setRG[i] == j)
ret += n[i]+" ";
}
ret +=",";         
}
return ret;
}
}

这个算法只是最原始最暴力最野蛮的穷举算法,在内存4G的机器上,对30个元素的集合,只能算到4以内的划分,后面就会导致JVM内存溢出,一般来说获取集合的划分并不会真的去得到所有划分,而只是寻找其中一些子集,就需要针对具体优化目标结合上述过程进行剪枝。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【摘要】 目前,对于聚类问题的研究普遍存在于社会生活中的各个领域,如模式识别、图像处理、机器学习和统计学等。关于对生活中各种各样的数据的聚类分类问题已经成为众多学者的研究热题之一。聚类和分类的区别在于,聚类没有任何先验知识可循,要通过数据自身的特点,将数据自动的划分到不同的类别中。聚类的基本形式定义为“在已给的数据集合中寻找数据点集的同类集合。每一个集合叫做一个类,并确定了一个区域,在区域中对象的密度高于其他区域中的密度。”聚类方法有很多种,其中最简单的形式便是划分式聚类,划分式聚类试图将给定的数据集合分割成不相交的子集,使具体的聚类准则是最优的。实际中应用最广泛的准则是聚类误差平方和准则,即对于每一个点都计算它到相应的聚类中心点的平方距离,并对数据集合上的所有点的距离进行和。一种最流行的基于最小聚类误差平法和的聚类方法是K-均值算法。然而,K-均值算法一个局部搜索的算法,它存在一些严重的不足,比如K值需要预先确定、聚类结果的好坏依赖于初始点的选取。为了解决这些问题,这个领域的研究者开发了很多其他的一些技术,试图基于全局最优化的方法来解决聚类问题(比如模拟退火算法、遗传算法等)。然而这些技术并没有得到广泛的认可,在许多实际应用中应用最多的还是反复利用K-均值算法。K-均值算法是一种基于划分的聚类算法,它通过不断的迭代来进行聚类,当算法收敛到一个结束条件时就终止迭代过程,输出聚类结果。由于其算法思想简便,又容易实现对大规模数据的聚类,因此K-均值算法已成为一种最常用的聚类算法之一K-均值算法能找到关于聚类误差的局部的最优解,是一个能应用在许多聚类问题上的快速迭代算法。它是一种以点为基础的聚类算法,以随机选取的初始点为聚类中心,迭代地改变聚类中心来使聚类误差最小化。这种方法最主要的不足就是对于初始聚类中心点位置的选取敏感。因此,为了得到近似最优解,初始聚类中心的位置必须安排的有差异。本文就K-均值聚类算法的聚类结果依赖于初始中心,而且经常收敛于局部最优解,而非全局最优解,以及聚类类别数K需要事先给定这两大缺憾展开研究。提出了分别解决这两个问题的算法一个首先,本文将Hae-Sang等人的快速K-中心点算法确定初始中心点的思想应用于Aristidis Likas的全局K-均值聚类算法中下一个簇的初始中心选择上,提出一种改进的全局K-均值聚类算法,试图寻找一个周围样本点分布比较密集,且距离现有簇的中心都较远的样本点,将其作为下一个簇的最佳初始中心。通过对UCI机器学习数据库数据及人工随机模拟数据的测试,证明本文算法与Aristidis Likas的全局K-均值聚类算法和快速全局K-均值聚类算法比,在不影响聚类误差平方和的前提下,聚类时间更短,具有更好的性能。同时,本文介绍了自组织特征映射网络(Self-Organizing Feature Map, SOFM)的相关内容,SOFM网络是将多维数据映射到低维规则网格中,可以有效的进行大规模的数据挖掘,其特点是速度快,但是分类的精度不高。而K-均值聚类算法,是一种通过不断迭代调整聚类质心的算法,其特点是精度高,主要用于中小数据集的分类,但是聚类速度比较慢。因此,本文在分析了基于自组织特征映射网络聚类的学习过程,权系数自组织过程中邻域函数,以及学习步长的一般取值问题后,给出了基于自组织特征映射网络聚类实现的具体算法,将自组织特征网络与K-均值聚类算法相结合,提出了一种基于自组织映射网络的聚类方法,来实现对输入模式进行聚类,实现K-均值聚类算法的聚类类别数的自动确定。同时通过实验进行仿真实现,证明该算法的有效性。 还原 【Abstract】 Clustering is a fundamental problem that frequently arises in a great variety of fields such as pattern recognition, image processing, machine learning and statistics. In general, clustering is defined as the problem of finding homogeneous groups of samples in a given data set. Each of these groups is called a cluster and can be defined as a region in which the density of exemplars is locally higher than in other regions.The simplest form of clustering is partition clustering w

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值