由一维数组表示的N维数组实现(C++)
工作中,经常需要表示多维数组(如二维矩阵),常见的做法是使用T **pArr;
T **pArr = new T*[M];//创建二维数组[M][N] for (int i=0;i<M;i++) {pArr[i] = new T[N]; }
销毁内存:
for (int i=0;i<M;i++) {delete[] pArr[i]; } delete[] pArr;
若是三维数组,需要创建三次,T*** pArr;以此类推,操作繁琐。
为方便动态生成多维数组,本文使用一维数据表示多维数组,并基于C++模板和运算符重载,使用一维数组动态表示多维数组,支持数据切片,简化多维数组的处理和使用。
#ifndef MYNDARRAY_H_20170226 #define MYNDARRAY_H_20170226#include <assert.h> #include <iostream> using namespace std;//on dim array represent n-dim array typedef unsigned int iNum;//使用unsigned int作为后续整数型数据类型 typedef struct stMyRange{//闭区间[start,end]iNum Start;//start 和end 从 0开始iNum End;// stMyRange(){Start = End = 0;}stMyRange(iNum start,iNum end){assert(start >= 0 && end >= start);Start = start;End = end;} }stMyRange;typedef struct stMyRank{//rank代表一个数据维度iNum Rank;//数据维度的长度 iNum Start;//数据维度开始位置,start from 0iNum End;//数据维度结束位置,start from 0stMyRank(){Rank = 0;//if dim == 0, this rank is not existStart = 0;//if start ==0 && end == Rank-1, reprsent the whole rank;End = 0;}void SetRank(iNum rank){assert(rank > 0);Rank = rank;Start = 0;End = Rank - 1;}void SetRange(stMyRange rang){assert(rang.Start >= 0 && rang.End >= rang.Start && rang.End < Rank);Start = rang.Start;End = rang.End;} }stMyRank; //目前设置最大数据维度为4,后续根据需要可扩展 #define MyMaxRank 4template<class T> class MyNDArray{//C++模板使用,可表示多种类型的数据 protected:T* m_pData;//row based storage,行优先存储 stMyRank m_Rank[MyMaxRank];//记录数据维度iNum m_iRankCap;//total rank capacity;数据维度个数bool m_isSlice;//if slice==true, it will reuse the m_pData of its parent;//是否是数据切片 public:MyNDArray(){m_pData = NULL;m_iRankCap = 0;m_isSlice = false;}MyNDArray(iNum rank1){m_Rank[0].SetRank(rank1);m_iRankCap = 1;m_isSlice = false;Init();}MyNDArray(iNum rank1,iNum rank2){m_Rank[0].SetRank(rank1);m_Rank[1].SetRank(rank2);m_iRankCap = 2;m_isSlice = false;Init();}MyNDArray(iNum rank1,iNum rank2,iNum rank3){m_Rank[0].SetRank(rank1);m_Rank[1].SetRank(rank2);m_Rank[2].SetRank(rank3);m_iRankCap = 3;m_isSlice = false;Init();}MyNDArray(iNum rank1,iNum rank2,iNum rank3,iNum rank4){m_Rank[0].SetRank(rank1);m_Rank[1].SetRank(rank2);m_Rank[2].SetRank(rank3);m_Rank[3].SetRank(rank4);m_iRankCap = 4;m_isSlice = false;Init();}//创建数据切片,新的ndarray共享partent的pData数据域MyNDArray(MyNDArray& parent,stMyRank rank1){m_Rank[0]=rank1;m_iRankCap = 1;m_isSlice = true;m_pData = parent.GetData();}MyNDArray(MyNDArray& parent,stMyRank rank1,stMyRank rank2){m_Rank[0]=rank1;m_Rank[1]=rank2;m_iRankCap = 2;m_isSlice = true;m_pData = parent.GetData();}MyNDArray(MyNDArray& parent,stMyRank rank1,stMyRank rank2,stMyRank rank3){m_Rank[0]=rank1;m_Rank[1]=rank2;m_Rank[2]=rank3;m_iRankCap = 3;m_isSlice = true;m_pData = parent.GetData();}MyNDArray(MyNDArray& parent,stMyRank rank1,stMyRank rank2,stMyRank rank3,stMyRank rank4){m_Rank[0]=rank1;m_Rank[1]=rank2;m_Rank[2]=rank3;m_Rank[3]=rank4;m_iRankCap = 4;m_isSlice = true;m_pData = parent.GetData();}~MyNDArray(){Clear();}void Clear(){if(!m_isSlice && m_pData != NULL){delete[] m_pData;m_pData = NULL;}}T* GetData(){return m_pData;}void SetData(T* pData){m_pData = pData;}iNum RankCap(){return m_iRankCap;}iNum RankSize(iNum rank){//start from 1,获取第i维的维度长度if(rank < 1) return 0;return m_Rank[rank-1].End - m_Rank[rank-1].Start + 1;}MyNDArray Slice(stMyRange rang1){//range start from 0,数据切片stMyRank rank1 = m_Rank[0];rank1.SetRange(rang1);MyNDArray res(*this,rank1);return res;}MyNDArray Slice(stMyRange rang1,stMyRange rang2){stMyRank rank1 = m_Rank[0];rank1.SetRange(rang1);stMyRank rank2 = m_Rank[1];rank2.SetRange(rang2);MyNDArray res(*this,rank1,rank2);return res;}MyNDArray Slice(stMyRange rang1,stMyRange rang2,stMyRange rang3){stMyRank rank1 = m_Rank[0];rank1.SetRange(rang1);stMyRank rank2 = m_Rank[1];rank2.SetRange(rang2);stMyRank rank3 = m_Rank[2];rank3.SetRange(rang3);MyNDArray res(*this,rank1,rank2,rank3);return res;}MyNDArray Slice(stMyRange rang1,stMyRange rang2,stMyRange rang3,stMyRange rang4){stMyRank rank1 = m_Rank[0];rank1.SetRange(rang1);stMyRank rank2 = m_Rank[1];rank2.SetRange(rang2);stMyRank rank3 = m_Rank[2];rank3.SetRange(rang3);stMyRank rank4 = m_Rank[3];rank4.SetRange(rang4);MyNDArray res(*this,rank1,rank2,rank3,rank4);return res;}//override operator(), 使用MyNDarray arr; arr(1,2,3,4)T& operator()(iNum r1=0,iNum r2=0,iNum r3=0,iNum r4=0){assert(m_pData != NULL);return m_pData[StoreIndex(r1,r2,r3,r4)];}const T& operator()(iNum r1=0,iNum r2=0,iNum r3=0,iNum r4=0) const{assert(m_pData != NULL);return m_pData[StoreIndex(r1,r2,r3,r4)];} protected:iNum StoreIndex(iNum r1,iNum r2,iNum r3,iNum r4){//数据存储引擎,以行优先存储assert(m_iRankCap > 0);if(m_isSlice){r1 += m_Rank[0].Start;r2 += m_Rank[1].Start;r3 += m_Rank[2].Start;r4 += m_Rank[3].Start;}//判断数据是否在合法的范围内if(m_iRankCap >= 1) assert(r1 >= m_Rank[0].Start && r1 <= m_Rank[0].End);if(m_iRankCap >= 2) assert(r2 >= m_Rank[1].Start && r2 <= m_Rank[1].End);if(m_iRankCap >= 3) assert(r3 >= m_Rank[2].Start && r3 <= m_Rank[2].End);if(m_iRankCap >= 4) assert(r4 >= m_Rank[3].Start && r4 <= m_Rank[3].End);iNum index = 0;index = r1 + m_Rank[0].Rank * (r2 + m_Rank[1].Rank * (r3 + m_Rank[2].Rank * r4));//row based storagereturn index;}void Init(){//初始化内存iNum size = 1; for (int i=0;i<m_iRankCap;i++){size *= m_Rank[i].Rank;}if(m_iRankCap > 0 && size > 0){m_pData = new T[size];}elsem_pData = NULL;} }; //重载输入>>和输出<<,用于数据读取和写入 //override operator >> template<class T> istream& operator >> (istream& myin,MyNDArray<T>& arr){iNum r1,r2,r3,r4;r1 = arr.RankSize(1);r2 = arr.RankSize(2);r3 = arr.RankSize(3);r4 = arr.RankSize(4);iNum rankCap = arr.RankCap();if(rankCap < 2) r2 = 1; if(rankCap < 3) r3 = 1; if(rankCap < 4) r4 = 1;for (int i4=0;i4<r4;i4++){for (int i3=0;i3<r3;i3++){for (int i2=0;i2<r2;i2++){for (int i1=0;i1<r1;i1++){myin >> arr(i1,i2,i3,i4);//调用重载的operator(),读取数据}}}}return myin; }//override operator << template<class T> ostream& operator << (ostream& myout,MyNDArray<T>& arr){iNum r1,r2,r3,r4;r1 = arr.RankSize(1);r2 = arr.RankSize(2);r3 = arr.RankSize(3);r4 = arr.RankSize(4);iNum rankCap = arr.RankCap();if(rankCap < 2) r2 = 1; if(rankCap < 3) r3 = 1; if(rankCap < 4) r4 = 1;for (int i4=0;i4<r4;i4++){myout<<"rank4:"<<i4+1<<endl;for (int i3=0;i3<r3;i3++){myout<<"rank3:"<<i3+1<<endl;for (int i2=0;i2<r2;i2++){for (int i1=0;i1<r1;i1++){myout <<arr(i1,i2,i3,i4)<<"\t";}myout<<"\n";}}myout<<"\n";}return myout; } #endif
使用方法:
int main(int argc, char* argv[]) {MyNDArray<int> ndarr(3,3,2,2);ifstream fin("ndarr.txt",ios::in);fin>>ndarr;cout<<ndarr;stMyRange range1(1,2);stMyRange range2(1,2);stMyRange range3(1,1);stMyRange range4(1,1);MyNDArray<int> slice = ndarr.Slice(range1,range2,range3,range4);cout<<"slice:"<<endl<<slice<<endl;cin>>ndarr;return 0; }
ndarr.txt内如如下:
1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 28 29 31 32 33 34 35 36 37 38 39
上述测试程序的输出结果为:
35 36
38 39
满足数据切片要求。
参考资料:
C++运算符重载:http://www.cnblogs.com/lfsblack/archive/2012/10/01/2709476.html
python.ndarray简单使用
C++ prime中的模板章节
转载于:https://www.cnblogs.com/hikeepgoing/p/6444327.html
由一维数组表示的N维数组实现(C++)相关推荐
- 【C 语言】数组 ( 一维数组形参退化 | 二维数组形参退化 | 函数形参等价关系 )
文章目录 一.一维数组形参退化 二.二维数组形参退化 三.数组形参等价关系 一.一维数组形参退化 C 中将 一维数组 作为参数 , 传递到函数中 , 该 一维数组 会退化为 指针 ; 将 int ar ...
- 【C 语言】数组 ( 验证二维数组内存是线性的 | 打印二维数组 | 以一维数组方式打印二维数组 | 打印二维数组值和地址 )
文章目录 一.验证二维数组内存是线性的 1.打印二维数组 2.以一维数组方式打印二维数组 3.打印二维数组值和地址 二.完整代码示例 一.验证二维数组内存是线性的 验证二维数组内存是线性的 : 验证方 ...
- 一维数组名与二维数组名的关联
1.一维数组名与二维数组名的关系之于普通指针与数组指针的关系 2.首先数组名编译器会隐式变换看做指针常量,因此a[i]与a+i是等价的. a+i返回由i指定的行地址,假设元素类型为char,则行指针类 ...
- 2022. 将一维数组转变成二维数组
2022. 将一维数组转变成二维数组 给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和 n .你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组 ...
- 一维数组转化为二维数组(java)
由于经常在使用矩阵进行计算时,会首先将一维数组转为二维数组.因此,在这里记录一下,也希望对他人有帮助. package deal; /** author:合肥工业大学 管院学院 钱洋 *1563178 ...
- PHP如何判断一个数组是一维数组或者是二维数组?用什么函数?
如题:如何判断一个数组是一维数组或者是二维数组?用什么函数? 判断数量即可 <?php if (count($array) == count($array, 1)) {echo '是一维数组'; ...
- 01背包和完全背包 的完整讲解版 包含 一维数组实现 和二维数组实现题目
(二)01背包和完全背包 的完整讲解版 包含 一维数组实现 和二维数组实现题目 //有N件物品和一个容量为V的背包.第i件物品的体积是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. ...
- oracle 一维数转二维数组,js将一维数组转化为二维数组
遇到的问题: 后端返回的是一组一维数组,但是需要展示的格式是二维数组,常见的场景举例:后台返回10个长度的数组,需要分成3个一组展示在banner上. 例:[1,2,3,4,5,6,7,8,9,10] ...
- 《c primer pius》第十章第6题,编写一个程序,初始化一个二维double数组,并利用练习2中的任一函数来把这个数组复制到另一个二维数组(因为二维数组是数组的数组,所以可以使用处理一维数组的
<c primer pius>第十章第6题,编写一个程序,初始化一个二维double数组,并利用练习2中的任一函数来把这个数组复制到另一个二维数组(因为二维数组是数组的数组,所以可以使用处 ...
- c语言一维数组转化为二维矩阵,js将一维数组转化为二维数组
遇到的问题: 后端返回的是一组一维数组,但是需要展示的格式是二维数组,常见的场景举例:后台返回10个长度的数组,需要分成3个一组展示在banner上. 例:[1,2,3,4,5,6,7,8,9,10] ...
最新文章
- 在PHP中使用全局变量的几种方法
- 栈与队列5——汉诺塔问题(方案二)
- Nature:大脑空间导航研究五十年
- libevent-signal(2)
- 世界应该多点理解关爱,少点争吵
- C++设计模式——简单工厂模式
- html概述和基本结构
- 软件项目管理0710:招标文件准备【求助】
- 跨国实时网络调度系统设计
- python科学计算与图形渲染_宁哥Python科学计算与图形渲染库课程
- 2018年终总结—努力做一个有趣的人
- linux切换到字符界面stemctl,CentOS7两种模式
- 如何将多个文件捆绑成一个可执行文件
- fastdfs文件上传 read timeout_一文看懂centos7系统部署FastDFS 分布式文件系统
- 铜川市2021年高考成绩查询,2021年铜川高考各高中成绩排名查询,铜川高考成绩公布榜单...
- UE4+LiveLinkFace面部动作捕捉
- 毕业论文答辩开题报告PPT模板
- 论BOM管理的若干重要问题
- 中外十大武侠片排行榜
- 为什么顶级程序员都有超强逆商?顶级程序员马化腾在艰难的时候,是如何度过的?
热门文章
- oracle执行计划结果分析_优化体系--sql整体优化(调优工具分析)
- Java数据结构:双向链表Double Linked List基础笔记
- 确定进制(经典水题)
- 【PAT】A-1034 :Head of a Gang(图的DFS遍历和map的巧妙使用---图的入门题目)
- 计算机VFP试题答案,计算机二级《VFP》试题及答案
- 南卫理公会大学 计算机排名,2020年南卫理公会大学Times世界排名
- sds数据结构,Simple Dynamic String,简单动态字符串
- 利用函数指针实现累加
- Container With Most Water(C++)
- python实现mapreduce求平均值