您的位置:首页 > 编程语言 > C语言/C++

全排列算法汇总(C++版)

2008-10-03 12:44 351 查看
全排列算法相信大家都比较熟悉了,这里只是对各种全排列算法进行一个汇总,让大家有个较全面的了解。由于有些版本被转载太多次了,故没法找到原创作者,这里就不特别注明了。

递归版本:

这是最通俗易懂的一个版本,不过网上流传的代码中第18行没有注释掉,我看了一下运行结果是一样的,只是顺序不一样。网上流传的版本在输出顺序上不是以递增的顺序出现,因为它每次交换过后又交换回来了。而注释掉的版本的输出顺序则是递增的顺序。
以下是代码:
/**
* Permutation helper.
* @param str original strings
* @return all the permutations
*/
void Permutation_Generator(string str, int m, int n, vector<string> &result)
{
if (m > n)
{
result.push_back(str);
}
else
{
for (int i = m; i <= n; ++i)
{
Swap<char>(str[m], str[i]);
Permutation_Generator(str, m + 1, n, result);
//Swap<char>(str[m], str[i]);
}
}
}

/**
* Get the permutation of the strings.
* @param str original strings
* @return all the permutations
*/
vector<string> Permutation(string str)
{
vector<string> result;
Permutation_Generator(str, 0, str.size() - 1, result);
return result;
}

非递归版本:
这个不是从网上看到的,是根据Kenneth H.Rosen的《离散数学及其应用的思路》写出来的。写得比较粗糙,还请见谅。

这个方法的主要思路是,根据当前序列确定下一个序列,直到某一条件被满足则所有序列遍历完成。

设一个序列为 {a1,a2, ... an}。我们的目的是要找到下一个排列。
1.我们要找到aj和aj+1,使得aj<aj+1且aj+1>aj+2>...>an。即找到两个元素,这两个元素后面的元素呈单减。
2.从aj+1开始,找到比aj大的最小的数ak,交换aj和ak。
3.对j位置之后的数进行升序排序,生成的序列便是下一个排列。
/**
* Get the permutation of the vectors.
* @param vec the vector that contains the elements
* @return the output of all the permutation sequence
*/
template <typename T>
vector<vector<T>> Permutation(vector<T> vec)
{
vector<vector<T>> retPerm;
retPerm.push_back(vec);
bool ret = true;
while(true == ret)
{
ret = Next_Permutation(vec);
if (ret)
{
retPerm.push_back(vec);
}
}

return retPerm;
}

/**
* Get the next permutation sequence according to the current sequence.
* @param vec current sequenece
* @return whether there exist next sequence
*/
template <typename T>
bool Next_Permutation(vector<T> &vec)
{
int i = vec.size() - 2;
// find the position that vec[i] <= vec[i]
while (i > 0 && vec[i] > vec[i + 1])
{
--i;
}

// find the least larger element located on the right side of vec[i]
int k = vec.size() - 1;
int leastLarger = -1;

for (int j = i; j < vec.size(); ++j)
{
if (vec[j] > vec[i])
{
leastLarger = j;
break;
}
}

if (leastLarger == -1)
{
return false;
}

while (k > i)
{
if ((vec[leastLarger] >= vec[k]) && (vec[k] > vec[i]))
{
leastLarger = k;
}
--k;
}

Swap(vec[i], vec[leastLarger]);

// sort the remain part of vector
vector<T>::iterator it = vec.begin();
for (int j = 0; j < i; ++j)
{
++it;
}
++it;

sort(it, vec.end());

return true;
}

以上便是最常用的两种方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: