如何为不同类型矩阵(deque/array of vectors等)泛化克罗内克积函数?
适配广义克罗内克积函数至多种矩阵类型
我已经实现了适用于std::vector<std::vector<T>>的广义克罗内克积函数,但目前卡在如何将其适配至其他类型矩阵(如std::deque<std::vector<T>>、std::array<std::vector<T>, N>等)的环节。我不确定是否应该、以及能否传入指向矩阵首尾的函数指针或迭代器,也不清楚这种方式是否适用于int array[]这类C风格数组。
原实现代码:
#include <iostream> #include <cmath> #include <vector> #include <deque> #include <iterator> #include <iomanip> template<typename T,typename T1,typename F> std::vector<std::vector<T>> GeneralizedKroneckerProduct(std::vector<std::vector<T>>M1, std::vector<std::vector<T>>M2, F &f ){ int m=M1.size(); int n=M1.at(0).size(); int p=M2.size(); int q=M2.at(0).size(); std::vector<std::vector<T1>>result(m*p,std::vector<T1>(n*q)); for(int i=0; i<m;i++){ for(int j=0; j<n;j++){ for(int k=0; k<p;k++){ for(int z=0; z<q;z++){ result.at(i*p+k).at(j*q+z)=f(M1.at(i).at(j),M2.at(k).at(z)); } } } } return result; } int main () { std::cout<<"Enter dimensions of the first matrix: "; int m=0,n=0; std::cin>>m>>n; std::cout<<"Enter elements of the first matrix: "; std::vector<std::vector<int>>A; std::vector<int>temp; int number; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ std::cin>>number; temp.push_back(number); } A.push_back(temp); temp.clear(); } std::cout<<"Enter dimensions of the second matrix: "; int p=0,q=0; std::cin>>p>>q; std::cout<<"Enter elements of the second matrix: "; std::vector<std::vector<int>>B; for(int i=0;i<p;i++){ for(int j=0;j<q;j++){ std::cin>>number; temp.push_back(number); } B.push_back(temp); temp.clear(); } auto f=[](int x, int y){return x*y;}; auto result=GeneralizedKroneckerProduct<int,int,decltype(f)>(A, B,f); std::cout<<"Their Kronecker product is: "<<std::endl; for(const auto &row:result){ for(const auto &number:row){ std::cout<<std::setw(5)<<number<<" "; } std::cout<<std::endl; } return 0; }
解决方案
1. 抽象容器类型为模板参数
将函数的输入矩阵类型改为模板参数,而非固定std::vector<std::vector<T>>,这样可以兼容所有支持size()和operator[]的二维容器(如std::deque、std::array):
template<typename Matrix1, typename Matrix2, typename F> auto GeneralizedKroneckerProduct(const Matrix1& M1, const Matrix2& M2, F&& f) { using T = typename Matrix1::value_type::value_type; using T1 = decltype(f(M1[0][0], M2[0][0])); const size_t m = M1.size(); const size_t n = M1[0].size(); const size_t p = M2.size(); const size_t q = M2[0].size(); // 默认返回vector<vector<T1>>,也可扩展为用户自定义返回类型 std::vector<std::vector<T1>> result(m * p, std::vector<T1>(n * q)); for (size_t i = 0; i < m; ++i) { for (size_t j = 0; j < n; ++j) { for (size_t k = 0; k < p; ++k) { for (size_t z = 0; z < q; ++z) { result[i * p + k][j * q + z] = f(M1[i][j], M2[k][z]); } } } } return result; }
2. 兼容C风格数组
C风格数组无法直接作为二维容器传递(会退化为指针),可以通过以下两种方式处理:
- 用
std::array包装C风格数组,例如std::array<std::array<int, 2>, 2> - 为C风格数组提供重载版本:
// 重载:处理C风格二维数组 template<typename T, size_t m, size_t n, typename U, size_t p, size_t q, typename F> auto GeneralizedKroneckerProduct(const T (&M1)[m][n], const U (&M2)[p][q], F&& f) { using T1 = decltype(f(M1[0][0], M2[0][0])); std::vector<std::vector<T1>> result(m * p, std::vector<T1>(n * q)); for (size_t i = 0; i < m; ++i) { for (size_t j = 0; j < n; ++j) { for (size_t k = 0; k < p; ++k) { for (size_t z = 0; z < q; ++z) { result[i * p + k][j * q + z] = f(M1[i][j], M2[k][z]); } } } } return result; }
3. 测试不同容器类型
修改后的函数可以直接支持std::deque、std::array等:
int main() { // 测试std::deque<std::vector<int>> std::deque<std::vector<int>> dq1 = {{1,2}, {3,4}}; std::deque<std::vector<int>> dq2 = {{5,6}, {7,8}}; auto dq_result = GeneralizedKroneckerProduct(dq1, dq2, [](int x, int y){return x*y;}); // 测试std::array<std::array<int,2>,2> std::array<std::array<int,2>,2> arr1 = {{{1,2}, {3,4}}}; std::array<std::array<int,2>,2> arr2 = {{{5,6}, {7,8}}}; auto arr_result = GeneralizedKroneckerProduct(arr1, arr2, [](int x, int y){return x*y;}); // 测试C风格数组 int c_arr1[2][2] = {{1,2}, {3,4}}; int c_arr2[2][2] = {{5,6}, {7,8}}; auto c_arr_result = GeneralizedKroneckerProduct(c_arr1, c_arr2, [](int x, int y){return x*y;}); // 输出结果 std::cout << "Deque result:\n"; for (const auto& row : dq_result) { for (int num : row) std::cout << std::setw(5) << num; std::cout << "\n"; } return 0; }
关键要点
- 使用模板参数抽象容器类型,避免绑定到具体的
std::vector - 通过
decltype自动推导返回值类型,无需手动指定T和T1 - 对C风格数组单独重载,利用模板非类型参数获取数组维度
- 优先使用
operator[]而非at()以提升性能(若需边界检查可保留at())
内容的提问来源于stack exchange,提问作者eminbihh
相关产品推荐
相关产品推荐

