【N个自然数的全排列问题】

1. 避免使用递归算法,因为这样会使计算复杂度成指数级别上升

  2. 巨大的计算量下,如何把计算工作切分成若干模块,并行。 现代计算机的特点是多核心,家用PC双核,四核,server上18路,36路核心。把大数据运算切分到各个核心上会事半功倍。

  因此我花了周六写了一个代码, 用非递归算法求全排列, 用特定的算法的把计算量分割成若干单元,用java线程池运算。 运算结果写本地文件。

  我的本地机器 2.93HZ双核CPU, 4G内存, win7系统,最高作了16个自然数的全排列,进行了一共4亿六千万次的运算,2分钟内完成。这个成绩还是可以的。

  更进一步,如果还想提高运算能力, 我会考虑用x86集群, 每个机器上启动一个JVM, 各个JVM之间tcp通信协同作业, 能将运算速度再提高一个数量级。

  有兴趣研究更深入算法或者技术实现的可以联系我,以下是我的代码:

  #代码开源共享,但是转载的时候请注明出处,谢谢合作!!

  [java]

  import java.io.FileWriter;

  import java.io.IOException;

  import java.math.BigInteger;

  import java.text.SimpleDateFormat;

  import java.util.ArrayList;

  import java.util.Arrays;

  import java.util.Collections;

  import java.util.Date;

  import java.util.concurrent.Callable;

  import java.util.concurrent.ExecutorService;

  import java.util.concurrent.Executors;

  import java.util.concurrent.Future;

  /**

  * 非递归算法 + 分割成若干计算单位并发运算

  * 在高计算量下会有明显优势,但是在计算量较小,线程切换会有开销

  * 本地机器 2.93HZ双核CPU, 4G内存, win7系统, 16个数的全排列,一共4亿7千万次运算,2分钟内完成

  * 如果更进一步,可以考虑用x86机器做集群运算,每个机器上启动一个JVM, JVM之间用tcp通信协调,一起跑

  * 有兴趣想深入研究可以联系我

  *

  * @author 蒋彪 版权所有 转载请注明出处

  * @param <E>

  * @param <T>

  * @mail nanjingjiangb@hotmail.com

  * @data 2013/3/4

  */

  public class CombinationTest<E> {

  // 计算模块的线程执行框架,线程数保持在CPU核数 + 1, 可以最大榨取机器性能

  // private final static ExecutorService exec = Executors

  // .newFixedThreadPool(1);

  private final static ExecutorService exec = Executors.newCachedThreadPool();

  public static void main(String[] args) {

  if (args.length < 1) {

  return;

  }

  // 先将这串数字正排序,预先处理

  Arrays.sort(args);

  ArrayList<Integer> min = Util.changeStringsToArray(args);

  Arrays.sort(args, Collections.reverseOrder());

  ArrayList<Integer> max = Util.changeStringsToArray(args);

  ArrayList diffBlock = getStepData(min, max);

  for (int k = 0; k < diffBlock.size() - 1; k++) {

  CombinationArg task = new CombinationArgNoRecursion();

  task.setPn((ArrayList<Integer>) diffBlock.get(k));

  task.setMax((ArrayList<Integer>) diffBlock.get(k + 1));

  Future future = exec.submit(task);

  // future.get();

  }

  // exec.shutdown();

  }

  /**

  * 分割待排序数据,分割成windows7旗舰版若干个起点的小块计算量 算法待优化,可考虑CPU,内存等限制计算快的大小

  *

  * @param pn

  * @return

  */

  public static ArrayList getStepData(ArrayList<Integer> min,

  ArrayList<Integer> max) {

  ArrayList result = new ArrayList();

  // 循环把第二位和第一位交换

posted on 2013-08-26 10:04  潇洒kman  阅读(388)  评论(0编辑  收藏  举报