函数模板实现——动态数组各元素的全排列问题







全排列


理论知识


全排列百度百科


运算公式

在这里插入图片描述

代码实现(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”模拟元素取舍进而解决组合问题(数组元素实现排列组合、字符串生成所有子序列、集合生成所有子集)



                                                                           转载请注明出处。
发布了89 篇原创文章 · 获赞 159 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/I_love_you_dandan/article/details/103210109