工作中,经常需要表示多维数组(如二维矩阵),常见的做法是使用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++)相关推荐

  1. 【C 语言】数组 ( 一维数组形参退化 | 二维数组形参退化 | 函数形参等价关系 )

    文章目录 一.一维数组形参退化 二.二维数组形参退化 三.数组形参等价关系 一.一维数组形参退化 C 中将 一维数组 作为参数 , 传递到函数中 , 该 一维数组 会退化为 指针 ; 将 int ar ...

  2. 【C 语言】数组 ( 验证二维数组内存是线性的 | 打印二维数组 | 以一维数组方式打印二维数组 | 打印二维数组值和地址 )

    文章目录 一.验证二维数组内存是线性的 1.打印二维数组 2.以一维数组方式打印二维数组 3.打印二维数组值和地址 二.完整代码示例 一.验证二维数组内存是线性的 验证二维数组内存是线性的 : 验证方 ...

  3. 一维数组名与二维数组名的关联

    1.一维数组名与二维数组名的关系之于普通指针与数组指针的关系 2.首先数组名编译器会隐式变换看做指针常量,因此a[i]与a+i是等价的. a+i返回由i指定的行地址,假设元素类型为char,则行指针类 ...

  4. 2022. 将一维数组转变成二维数组

    2022. 将一维数组转变成二维数组 给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和 n .你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组 ...

  5. 一维数组转化为二维数组(java)

    由于经常在使用矩阵进行计算时,会首先将一维数组转为二维数组.因此,在这里记录一下,也希望对他人有帮助. package deal; /** author:合肥工业大学 管院学院 钱洋 *1563178 ...

  6. PHP如何判断一个数组是一维数组或者是二维数组?用什么函数?

    如题:如何判断一个数组是一维数组或者是二维数组?用什么函数? 判断数量即可 <?php if (count($array) == count($array, 1)) {echo '是一维数组'; ...

  7. 01背包和完全背包 的完整讲解版 包含 一维数组实现 和二维数组实现题目

    (二)01背包和完全背包 的完整讲解版 包含 一维数组实现 和二维数组实现题目 //有N件物品和一个容量为V的背包.第i件物品的体积是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. ...

  8. oracle 一维数转二维数组,js将一维数组转化为二维数组

    遇到的问题: 后端返回的是一组一维数组,但是需要展示的格式是二维数组,常见的场景举例:后台返回10个长度的数组,需要分成3个一组展示在banner上. 例:[1,2,3,4,5,6,7,8,9,10] ...

  9. 《c primer pius》第十章第6题,编写一个程序,初始化一个二维double数组,并利用练习2中的任一函数来把这个数组复制到另一个二维数组(因为二维数组是数组的数组,所以可以使用处理一维数组的

    <c primer pius>第十章第6题,编写一个程序,初始化一个二维double数组,并利用练习2中的任一函数来把这个数组复制到另一个二维数组(因为二维数组是数组的数组,所以可以使用处 ...

  10. c语言一维数组转化为二维矩阵,js将一维数组转化为二维数组

    遇到的问题: 后端返回的是一组一维数组,但是需要展示的格式是二维数组,常见的场景举例:后台返回10个长度的数组,需要分成3个一组展示在banner上. 例:[1,2,3,4,5,6,7,8,9,10] ...

最新文章

  1. 在PHP中使用全局变量的几种方法
  2. 栈与队列5——汉诺塔问题(方案二)
  3. Nature:大脑空间导航研究五十年
  4. libevent-signal(2)
  5. 世界应该多点理解关爱,少点争吵
  6. C++设计模式——简单工厂模式
  7. html概述和基本结构
  8. 软件项目管理0710:招标文件准备【求助】
  9. 跨国实时网络调度系统设计
  10. python科学计算与图形渲染_宁哥Python科学计算与图形渲染库课程
  11. 2018年终总结—努力做一个有趣的人
  12. linux切换到字符界面stemctl,CentOS7两种模式
  13. 如何将多个文件捆绑成一个可执行文件
  14. fastdfs文件上传 read timeout_一文看懂centos7系统部署FastDFS 分布式文件系统
  15. 铜川市2021年高考成绩查询,2021年铜川高考各高中成绩排名查询,铜川高考成绩公布榜单...
  16. UE4+LiveLinkFace面部动作捕捉
  17. 毕业论文答辩开题报告PPT模板
  18. 论BOM管理的若干重要问题
  19. 中外十大武侠片排行榜
  20. 为什么顶级程序员都有超强逆商?顶级程序员马化腾在艰难的时候,是如何度过的?

热门文章

  1. oracle执行计划结果分析_优化体系--sql整体优化(调优工具分析)
  2. Java数据结构:双向链表Double Linked List基础笔记
  3. 确定进制(经典水题)
  4. 【PAT】A-1034 :Head of a Gang(图的DFS遍历和map的巧妙使用---图的入门题目)
  5. 计算机VFP试题答案,计算机二级《VFP》试题及答案
  6. 南卫理公会大学 计算机排名,2020年南卫理公会大学Times世界排名
  7. sds数据结构,Simple Dynamic String,简单动态字符串
  8. 利用函数指针实现累加
  9. Container With Most Water(C++)
  10. python实现mapreduce求平均值