原创:全排列非递归算法:微软给出的算法
关于全排列的算法研究,有很多,不论述了。采用非递归的算法,是首选。直接上传微软给出的算法:
/*
* 字符串全排列最优算法(非递归置换)
*/
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--;
}
}
}
}