用三个vector容器解决全排列问题


全排列如果用伪代码描述是很容易理解的,但是用代码实现却有点不容易。

首先是伪代码:先将可以进行全排列的函数设为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();
			}
		}
	}
}


其实还是可以创建一个返回值为容器,参数为容器的函数,但是因为个人原因,把声明部分的参数写错了,而且还没发现,结果代码死活过不了,导致最后用了三个容器去解决了。

猜你喜欢

转载自blog.csdn.net/SeptDays/article/details/78570519