函數模板實現——動態數組各元素的全排列問題







全排列


理論知識


全排列百度百科


運算公式

在這裏插入圖片描述

代碼實現(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”模擬元素取捨進而解決組合問題(數組元素實現排列組合、字符串生成所有子序列、集合生成所有子集)



                                                                           轉載請註明出處。
發佈了88 篇原創文章 · 獲贊 230 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章