全排列如果用伪代码描述是很容易理解的,但是用代码实现却有点不容易。
首先是伪代码:先将可以进行全排列的函数设为Permutation, 将要输入的字符串设为S,遍历字符串取一个字符存入resutl中,再在剩下的字符串进行遍历,如果字符串只剩一个直接返回即:
def Permutation(S):lenstr=len(S)if lenstr<=1:return Selse 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();}}}
}
其实还是可以创建一个返回值为容器,参数为容器的函数,但是因为个人原因,把声明部分的参数写错了,而且还没发现,结果代码死活过不了,导致最后用了三个容器去解决了。