全排列如果用伪代码描述是很容易理解的,但是用代码实现却有点不容易。
首先是伪代码:先将可以进行全排列的函数设为Permutation, 将要输入的字符串设为S,遍历字符串取一个字符存入resutl中,再在剩下的字符串进行遍历,如果字符串只剩一个直接返回即:
def Permutation(S):
lenstr=len(S)
if lenstr<=1:
return S
else result=[]
for i in range(lenstr):
ch=S[i]
rest=S[0:i]+S[i+i:-1]
for p in p(rest) :
result.append(ch+p)
return result
但对c++来说有点困难,因为不知道输入的字符串的长度,而且我还想用非字典序的方式来做。自己挖的坑,跪着也要填完。
在用vector的过程我遇到好几个坑点。
第一个,如何将每次递归的结果存储或输出
第二个,如果只是单纯地将遍历到的数字erase()出去,那必须在遍历之后,将数字添加回去。但是vector有个令人头痛的地方,如果 S.erase(p); ,则p之后就无法在用,也无法通过p在原先删除过数字的地方添加数字。如果是p=S.erase(p); 就会发现在vector末尾删除数字后,再想直接S.insert(p)又有问题。
最后,折磨了半天,只能这样做
用容器A来存储输入的字符串,用容器B来标识A中的容器是否已经输出,用容器C来存储要输出的字符串
代码如下:
#include<iostream>
#include<vector>
using namespace std;
static vector<char>temp;//存储要输出的内容
static vector<int>index;//存储容量标记
void P(vector<char>&line);//提前声明函数
int lenstr;//存储容量长度
int main()
{
while (1)
{
temp.clear();
index.clear();
char a;
vector<char>line;
cout << "请输入以'#'为结尾的字符串:" << endl;
while (cin >> a && a != '#')
{
line.push_back(a);
}
lenstr = line.size();
index.resize(lenstr);
P(line);
}
}
void P(vector<char>&line)
{
char ch;
if (line.size() == temp.size())
{
//temp.push_back(line[0]);
for (unsigned int i = 0; i < temp.size(); i++)
cout << temp[i];
cout << endl;
//temp.pop_back();//将输出过的最后一个字母删除
}
else
{
for (unsigned int j = 0; j < line.size(); j++)
{
if (!index[j])
{
ch = line[j];
temp.push_back(ch);//将字符添加到输出容量
index[j] = 1;//将已添加字符标记
P(line);
index[j] = 0;//去除标记
temp.pop_back();
}
}
}
}
其实还是可以创建一个返回值为容器,参数为容器的函数,但是因为个人原因,把声明部分的参数写错了,而且还没发现,结果代码死活过不了,导致最后用了三个容器去解决了。