YY呀 ~ 我們不做陌生人,好不好? —— 樹洞
全排列
理論知識
全排列百度百科
運算公式
代碼實現(C++)
std::prev_permutation,按字典降序全排列
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
// 初始化;
template<typename T>
std::vector<T> inputData(T&, const int&);
// 輸出一維數組;
template<typename T>
void outputData(const std::vector<T>&);
// 降序標誌;
template<typename T>
bool cmp(T& a, T& b) {
return a > b;
}
// 降序全排列;
template <typename T>
void permutationDownwards(std::vector<T>&);
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int num; // 待排列的元素個數;
while (std::cin >> num) {
std::string str; // 元素類型爲字符串;
//char ch; // 元素類型爲字符;
//int n; // 元素類型爲整型數;
// 好似 python 的設計那般,整型數、字符都可以作爲 “字符串” 進行處理;
// 輸入;
//std::vector<std::string> vs = inputData(str, num);
auto vs = inputData(str, num);
// 輸出;
//outputData(vs);
// 全排列;
permutationDownwards(vs);
}
return 0;
}
template<typename T>
std::vector<T> inputData(T& temp, const int& num) {
std::vector<T> vt;
for (int i = 0; i < num; ++i) {
std::cin >> temp;
vt.push_back(temp);
}
return vt;
}
template<typename T>
void outputData(const std::vector<T>& myvec) {
for (auto iter : myvec) {
std::cout << iter << " ";
}
std::cout << std::endl;
}
template <typename T>
void permutationDownwards(std::vector<T>& myvec) {
std::sort(std::begin(myvec), std::end(myvec), cmp<T>);
int t = 0;
do {
++t;
outputData(myvec);
} while (std::prev_permutation(std::begin(myvec), std::end(myvec)));
std::cout << t << " runs" << std::endl;
}
測試樣例及其結果
std::next_permutation,按字典升序全排列
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
// 初始化;
template<typename T>
std::vector<T> inputData(T&, const int&);
// 輸出一維數組;
template<typename T>
void outputData(const std::vector<T>&);
// vector 轉 數組;
template<typename T>
T* vecToArr(const std::vector<T>&);
// 升序全排列;
template <typename T>
void permutationUpwards(T[], const int&);
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int num; // 待排列的元素個數;
while (std::cin >> num) {
std::string str;
// 輸入;
//std::vector<std::string> vs = inputData(str, num);
auto vs = inputData(str, num);
// 輸出;
//outputData(vs);
auto strArr = vecToArr(vs);
permutationUpwards(strArr,vs.size());
//std::cout << "*strArr = " << strArr << std::endl; // 經驗證,確爲同一地址,可以 delete
delete[] strArr;
}
return 0;
}
template<typename T>
T* vecToArr(const std::vector<T>& myvec) {
T* arr = new T[myvec.size()];
if (arr) {
int index = 0;
for (auto iter : myvec) {
arr[index++] = iter;
}
}
//std::cout <<"*arr = "<< arr << std::endl; // 輸出所開闢空間的首地址
return arr;
}
template<typename T>
std::vector<T> inputData(T& temp, const int& num) {
std::vector<T> vt;
for (int i = 0; i < num; ++i) {
std::cin >> temp;
vt.push_back(temp);
}
return vt;
}
template<typename T>
void outputData(const std::vector<T>& myvec) {
for (auto iter : myvec) {
std::cout << iter << " ";
}
std::cout << std::endl;
}
template <typename T>
void permutationUpwards(T arr[], const int& len) { // int,double,float,char 型數組;
std::sort(arr, arr + len);
int t = 0;
do {
++t;
for (int i = 0; i < len; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
} while (std::next_permutation(arr, arr + len));
std::cout << t << " runs" << std::endl;
}
測試樣例及其結果
#### 標配模板
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
// 初始化;
template<typename T>
std::vector<T> inputData(T&, const int&);
// 輸出二維數組,函數重載;
template<typename T>
void outputData(const std::vector<std::vector<T>>&);
// 降序標誌;
template<typename T>
bool cmp(T& a, T& b) {
return a > b;
}
// 全排列標配模板;
template < typename T>
std::vector<std::vector<T>> permutation(std::vector<T>&);
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int num; // 待排列的元素個數;
while (std::cin >> num) {
std::string str;
auto vs = inputData(str, num);
auto vvs = permutation(vs);
outputData(vvs);
}
return 0;
}
template<typename T>
std::vector<T> inputData(T& temp, const int& num) {
std::vector<T> vt;
for (int i = 0; i < num; ++i) {
std::cin >> temp;
vt.push_back(temp);
}
return vt;
}
template<typename T>
void outputData(const std::vector<std::vector<T>>& myvv) {
for (auto iter : myvv) {
for (auto it : iter) {
std::cout << it << " ";
}
std::cout << std::endl;
}
}
template < typename T>
std::vector<std::vector<T>> permutation(std::vector<T>& myvec) {
//std::sort(std::begin(myvec), std::end(myvec));
std::sort(std::begin(myvec), std::end(myvec), cmp<T>);
std::vector<std::vector<T>> vvs;
do {
vvs.push_back(myvec);
} //while (std::next_permutation(std::begin(myvec), std::end(myvec)));
while (std::prev_permutation(std::begin(myvec), std::end(myvec)));
std::cout << vvs.size() << " runs" << std::endl;
return vvs;
}
可升序
亦可降序
升降序說明
完整Project
//#include<bits/stdc++.h>
//#include <iostream>
//#include <vector>
//#include <string>
//#include <algorithm>
#include<bits/stdc++.h>
// 初始化;
template<typename T>
std::vector<T> inputData(T&, const int& );
// 輸出一維數組;
template<typename T>
void outputData(const std::vector<T>& );
// 輸出二維數組,函數重載;
template<typename T>
void outputData(const std::vector<std::vector<T>>&);
// 降序標誌;
template<typename T>
bool cmp(T& a, T& b) {
return a > b;
}
// 降序全排列;
template <typename T>
void permutationDownwards(std::vector<T>& );
// vector 轉 數組;
template<typename T>
T* vecToArr(const std::vector<T>& );
// 升序全排列;
template <typename T>
void permutationUpwards(T [], const int& );
// 全排列標配模板;
template < typename T>
std::vector<std::vector<T>> permutation(std::vector<T>& );
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int num; // 待排列的元素個數;
while (std::cin >> num) {
std::string str; // 元素類型爲字符串;
//char ch; // 元素類型爲字符;
//int n; // 元素類型爲整型數;
// 好似 python 的設計那般,整型數、字符都可以作爲 “字符串” 進行處理;
// 輸入;
//std::vector<std::string> vs = inputData(str, num);
auto vs = inputData(str, num);
// 輸出;
//outputData(vs);
//// 全排列;
//permutationDownwards(vs);
//auto strArr = vecToArr(vs);
//permutationUpwards(strArr,vs.size());
////std::cout << "*strArr = " << strArr << std::endl; // 經驗證,確爲同一地址,可以 delete
//delete[] strArr;
auto vvs = permutation(vs);
outputData(vvs);
}
return 0;
}
template<typename T>
T* vecToArr(const std::vector<T>& myvec) {
T* arr = new T[myvec.size()];
if (arr) {
int index = 0;
for (auto iter : myvec) {
arr[index++] = iter;
}
}
//std::cout <<"*arr = "<< arr << std::endl; // 輸出所開闢空間的首地址
return arr;
}
template<typename T>
std::vector<T> inputData(T& temp, const int& num) {
std::vector<T> vt;
for (int i = 0; i < num; ++i) {
std::cin >> temp;
vt.push_back(temp);
}
return vt;
}
template<typename T>
void outputData(const std::vector<T>& myvec) {
for (auto iter : myvec) {
std::cout << iter << " ";
}
std::cout << std::endl;
}
template<typename T>
void outputData(const std::vector<std::vector<T>>& myvv) {
for (auto iter : myvv) {
for (auto it : iter) {
std::cout << it << " ";
}
std::cout << std::endl;
}
}
template <typename T>
void permutationDownwards(std::vector<T>& myvec) {
std::sort(std::begin(myvec), std::end(myvec), cmp<T>);
int t = 0;
do {
++t;
outputData(myvec);
} while (std::prev_permutation(std::begin(myvec), std::end(myvec)));
std::cout << t << " runs" << std::endl;
}
template <typename T>
void permutationUpwards(T arr[], const int& len) { // int,double,float,char 型數組;
std::sort(arr, arr + len);
int t = 0;
do {
++t;
for (int i = 0; i < len; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
} while (std::next_permutation(arr, arr + len));
std::cout << t << " runs" << std::endl;
}
template < typename T>
std::vector<std::vector<T>> permutation(std::vector<T>& myvec) {
//std::sort(std::begin(myvec), std::end(myvec));
std::sort(std::begin(myvec), std::end(myvec), cmp<T>);
std::vector<std::vector<T>> vvs;
do {
vvs.push_back(myvec);
} //while (std::next_permutation(std::begin(myvec), std::end(myvec)));
while (std::prev_permutation(std::begin(myvec), std::end(myvec)));
std::cout << vvs.size() << " runs" << std::endl;
return vvs;
}
## 後記 #### 數據結構選擇 ```bash 原本並不是通過vector實現數據存儲的,一開始用的 set,想着可以直接免了排序的工作; 但由於set 並非是 地址連續的內存空間塊,無法使用上樹的兩個全排列函數。 ``` #### for each 語法
for(auto i : container){ …; }
僅針對容器使用,對定長數組無法使用。
自己兩年前的代碼實現
錯排序列與錯排數
待更。
組合問題
詳見另外一篇博文:
通過二進制串“01”模擬元素取捨進而解決組合問題(數組元素實現排列組合、字符串生成所有子序列、集合生成所有子集)
轉載請註明出處。