原创:全排列非递归算法:微软给出的算法

关于全排列的算法研究,有很多,不论述了。采用非递归的算法,是首选。直接上传微软给出的算法:

/*
  * 字符串全排列最优算法(非递归置换)
  */
 public void permutation(char str[],int m,boolean duplicate){
  int n = str.length;
  if(n < 1 || m < 0 || m > n)
         return;

     if(m == 0) //默认全排列

         m = n;

     int repeat_cnt[] = new int[n]; //循环计数器,一层一个,共 n 个,都初始化为 0
     char tmp_seq[] = new char[n];  //存放排列结果序列的空间
     int layer = 0;                  //当前正在循环层

     int pos;                        //本循环层的层计数器

     while(true)
     {
         if(layer == 0 && repeat_cnt[0] >= n) //当前在第0层,且第0层计数器达到末尾时退出循环
             break;
         if(layer < m - 1)           //小于n-1层
         {
             pos = repeat_cnt[layer];
             if(pos < n)
             {

                 //层计数器 < n,保存层计数器指向的元素,计数器前进一位,增加一层
                 if(!duplicate)
                 {

                     //不允许重复
                     boolean found = false;
                     for(int i = 0; i < n; ++i)
                     {
                         if(pos + 1 == repeat_cnt[i])
                         {
                             found = true;
                             break;
                         }
                     }
                     if(found)
                     {

                         //检查到重复,计数器前进一位,继续
                         repeat_cnt[layer] = repeat_cnt[layer] + 1;
                         continue;
                     }
                 }
                 tmp_seq[layer] = str[pos];
                 repeat_cnt[layer] = repeat_cnt[layer] + 1;
                 layer++;
             }                //否则,层计数器归零,向上一层

             else
             {

                 //否则,层计数器归零,向上一层
                 repeat_cnt[layer] = 0;
                 layer--;
             }
         }
         else
         {//处理最后一层

             //第 m - 1 层:计数器每移动一个位置,都是一种组合
             pos = repeat_cnt[layer];
             if(pos < n)
             {
                 if(!duplicate)
                 {

                     //不允许重复
                     boolean found = false;
                     for(int i = 0; i < n; ++i)
                     {
                         if(pos + 1 == repeat_cnt[i])
                         {
                             found = true;
                             break;
                         }
                     }
                     if(found)
                     {

                         //检查到重复,计数器前进一位,继续
                         repeat_cnt[layer] = repeat_cnt[layer] + 1;
                         continue;
                     }
                 }

                 tmp_seq[layer] = str[pos];

                 //找到一种组合,将其打印出来

                 for(int i = 0; i < n; ++i)
                     System.out.print(tmp_seq[i]);
                  System.out.println();

                 //层计数器前进 1 位

                 repeat_cnt[layer] = repeat_cnt[layer] + 1;
             }
             else
             {

                 //n-1 层计数器到达末尾,将层计数器归零 ,返回上层
                 repeat_cnt[layer] = 0;
                 layer--;
             }
         }
     }
 }

posted @ 2016-11-23 17:05  佟学强  阅读(252)  评论(0编辑  收藏  举报