您的位置:首页 > 编程语言 > Java开发

Java实现基于数值编码原理的组合算法(多线程)

2012-02-11 10:10 716 查看
转自:http://hi.baidu.com/shirdrn/blog/item/b82c2ad3f886593d970a16b0.html

基于数值编码原理的组合算法思想:

本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标 代表的数被选中,为0则没选中。

首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为 “01”组合,同时将其左边的所有“1”全部移动到数组的最左端。 当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。

该思想是基于数值编码原理的,在Java中可以使用BitSet来代替一个数组,用来表示某个字符串的某些位是否被占用,如果被占用,则为true,并根据上述思想构造的BitSet来确定某一个组合。

例如,对字符串12345进行5取2组合:

11100 -> ***45

11010 -> **3*5

10110 -> *2**5

01110 -> 1***5

11001 -> **34*

10101 -> *2*4*

01101 -> 1**4*

10011 -> *23**

10100 -> 1*3**

00111 -> 12***

使用Java实现基于多线程的组合算法,更多的地方需要同步访问,在一定程度上能够提高并行度,提高计算速度。实现代码如下所示:

package org.shirdrn;

import java.util.ArrayList;

import java.util.BitSet;

import java.util.Collection;

import java.util.Collections;

import java.util.HashSet;

import java.util.Iterator;

/**

* 组合拆分类

*

* 根据从复式投注字符串经过拆分过滤后得到的单式投注字符串集合,对其中每一个单式投注字符串进行组合<br>

* 例如:输入集合{31311133,33113330},Splitter类会遍历该集合,对每个单式投注注字符串,创建一个SplitterThread<br>

* 线程来处理,如果是2串1组合,即starCount=8-2=6,经过线程处理得到类似******33,*****1*3等结果

*

* @author shirdrn

*

*/

public class MySplitter {

private Iterator<String> iterator;

private int length;

private int starCount;

private boolean duplicate;

private Collection<String> filteredContainer;

private Boolean finished = false;

private Integer threadCount;

private int splitSize = 100;

public Collection<String> getFilteredContainer() {

while(!finished) {

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

return filteredContainer;

}

/**

* 构造一个Spilitter实例

*

* @param container 从复式投注字符串经过拆分过滤后得到的单式投注字符串集合

* @param starCount 如果对于N长比赛,进行M组合过关,则starCount=N-M

* @param duplicate 是否去重

*/

public MySplitter(Collection<String> container, int starCount, boolean duplicate) {

this.iterator = container.iterator();

this.duplicate = duplicate;

this.starCount = starCount;

if(this.duplicate) { // 根据指定是否去重的选择,选择创建容器

filteredContainer = Collections.synchronizedSet(new HashSet<String>());

}

else {

filteredContainer = Collections.synchronizedList(new ArrayList<String>());

}

Iterator<String> it = container.iterator();

this.length = it.next().trim().length();

this.threadCount = container.size()/splitSize;

for(int i=0; i<this.threadCount; i++) {

new Thread(new SplitterThread()).start();

}

}

/**

* 对一个指定的N场比赛的长度为N的单式投注字符串进行组合<br>

* 输入单式投注注字符串string,例如31311133,组合得到类似******33,*****1*3,... ...结果的集合

*

* @author shirdrn

*

*/

class SplitterThread implements Runnable {

public SplitterThread() {

}

public void run() {

boolean flag = true;

while(flag) {

Collection<String> c;

if(duplicate) { // 根据指定是否去重的选择,选择创建线程的私有容器

c = new HashSet<String>();

}

else {

c = new ArrayList<String>();

}

String string = "";

synchronized(iterator) { // 需要同步待处理字符串集合的迭代器实例,迭代一条记录进行处理

if(iterator.hasNext()) {

string = iterator.next();

}

else {

synchronized(threadCount) { // 同步线程统计变量,用于监测当前线程总数,即使Kill掉完成任务的线程

threadCount--;

if(threadCount == 0) {

finished = true;

flag = false;

}

break;

}

}

}

this.split(string, c);

synchronized(filteredContainer) { // 同步处理后的集合,将处理结果整合到容器中

filteredContainer.addAll(c);

}

}

}

public void split(String string, Collection<String> c) {

char[] charArray = string.toCharArray();

BitSet startBitSet = new BitSet(length); // 比特集合起始状态

BitSet endBitSet = new BitSet(length); // 比特集合终止状态,用来控制循环

// 初始化startBitSet,左侧占满*符号

for (int i = 0; i < starCount; i++) {

startBitSet.set(i, true);

}

// 初始化endBit,右侧占满*符号

for (int i = length - 1; i > length - starCount - 1; i--) {

endBitSet.set(i, true);

}

// 根据起始startBitSet,构造带*的组合字符串并加入容器

char[] charArrayClone = charArray.clone();

for (int i = 0; i < length - 1; i++) {

if (startBitSet.get(i)) {

charArrayClone[i] = '*';

}

}

c.add(new String(charArrayClone));

while (!startBitSet.equals(endBitSet)) {

int zeroCount = 0; // 统计遇到10后,左边0的个数

int oneCount = 0; // 统计遇到10后,左边1的个数

int pos = 0; // 记录当前遇到10的索引位置

charArrayClone = charArray.clone();

// 遍历startBitSet来确定10出现的位置

for (int i = 0; i < length - 1; i++) {

if (!startBitSet.get(i)) {

zeroCount++;

}

if (startBitSet.get(i) && !startBitSet.get(i + 1)) {

pos = i;

oneCount = i - zeroCount;

startBitSet.set(i, false);

startBitSet.set(i + 1, true);

break;

}

}

// 将遇到10后,左侧的1全部移动到最左侧

int count = Math.min(zeroCount, oneCount);

int startIndex = 0;

int endIndex = pos - 1;

for (int i = 0; i < count; i++) {

startBitSet.set(startIndex, true);

startBitSet.set(endIndex, false);

startIndex++;

endIndex--;

}

// 将遇到1的位置用*替换

for (int i = 0; i < length; i++) {

if (startBitSet.get(i)) {

charArrayClone[i] = '*';

}

}

c.add(new String(charArrayClone));

}

}

}

}

测试用例如下所示:

package org.shirdrn;

import java.util.Collection;

import com.zucai310.Zucai310;

import junit.framework.TestCase;

public class TestMySplitter extends TestCase {

private MySplitter splitter;

public void setMySplitter(Collection<String> container, int starCount, boolean duplicate) {

this.splitter = new MySplitter(container, starCount, duplicate);

}

public void testMySplitter_8_310() {

// 8 场:310

String multiSeq = "310,310,310,310,310,310,310,310";

Collection<String> container = Zucai310.getNSingleList(multiSeq);

assertEquals(6561, container.size());

int starCount = 4;

boolean duplicate = false;

this.setMySplitter(container, starCount, duplicate);

assertEquals(459270, this.splitter.getFilteredContainer().size());

}

public void testMySplitter_9_1() {

// 9 场:310,310,310,310,310,310,310,310,3

String multiSeq = "310,310,310,310,310,310,310,310,3";

Collection<String> container = Zucai310.getNSingleList(multiSeq);

assertEquals(6561, container.size());

int starCount = 4;

boolean duplicate = false;

this.setMySplitter(container, starCount, duplicate);

assertEquals(826686, this.splitter.getFilteredContainer().size());

}

public void testMySplitter_9_2() {

// 9 场:310,310,310,310,310,310,310,310,3

String multiSeq = "310,310,310,310,310,310,31,31,31";

Collection<String> container = Zucai310.getNSingleList(multiSeq);

assertEquals(5832, container.size());

int starCount = 4;

boolean duplicate = false;

this.setMySplitter(container, starCount, duplicate);

assertEquals(734832, this.splitter.getFilteredContainer().size());

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: