- 浏览: 265528 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
daknife:
谢谢你的这篇文章,让我大概了解了select的一部分底层原理。 ...
Linux-2.6.25 select系统调用源码分析 -
gjlzjb:
非常有用,谢谢哈。另外问下,您是否用过Pheonix Syst ...
Why Map/Reduce? -
zhangyafei_kimi:
canbo 写道请问,我怎么生成安装包,提供给其它用户安装呢? ...
下载最新的Google Chrome源码并编译 -
canbo:
请问,我怎么生成安装包,提供给其它用户安装呢?
下载最新的Google Chrome源码并编译
#ifndef __KIMI_BOOST_ARRAY2
#define __KIMI_BOOST_ARRAY2
#pragma once
#include <cstddef> //size_t
#include <exception>//exception
#include <iterator>//random_access_iterator_tag,reverse_iterator
namespace kimi_boost
{
template <class T> class array2;//forward declaration
//iterator for class array2
template <class T,class Ref,class Ptr>
struct __M_array2_iterator
{
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef Ptr pointer;
typedef Ref reference;
typedef __M_array2_iterator self;
std::size_t m;//index1
std::size_t n;//index2
array2<T>* m_pArray;//pointer to current array2 object
__M_array2_iterator():m(0),n(0),m_pArray(0){}
__M_array2_iterator(std::size_t m1, std::size_t n1, array2<T>* pArray)
:m(m1),n(n1),m_pArray(pArray){}
__M_array2_iterator(const __M_array2_iterator& y)
:m(y.m),n(y.n),m_pArray(y.m_pArray){}
reference operator*()const{return m_pArray->at(m,n);}
pointer operator->()const{return &(this->operator *());}
//necessary operators for a bidirectional iterator
self& operator++()
{
if(n < m_pArray->size2()-1) ++n;
else if (n == m_pArray->size2()-1 && m < m_pArray->size1()-1){n=0;++m;}
else n=m_pArray->size2();//pass the last element : end
return *this;
}
self operator++(int)
{
self temp=*this;
++*this;
return temp;
}
self& operator--()
{
if(n > 0) --n;
else if (n == 0 && m > 0){n=m_pArray->size2()-1;--m;}
return *this;
}
self operator--(int)
{
self temp=*this;
--*this;
return temp;
}
bool operator==(const self& x)const
{
return m_pArray==x.m_pArray && m==x.m && n==x.n;
}
bool operator!=(const self& x)const
{
return !operator ==(x);
}
//necessary operators for a random access iterator
difference_type operator-(const self& x)const
{
return difference_type( (m-x.m)*m_pArray->size2() + n-x.n );
}
self& operator += (difference_type x)
{
difference_type size2=m_pArray->size2();
difference_type total = n+x;
difference_type new_m = static_cast<difference_type>(m) + total/size2;
difference_type new_n = total%size2;
if( new_m >= static_cast<difference_type>(m_pArray->size1()) )//pass end(),and restrict to end()
{
m=m_pArray->size1()-1;
n=m_pArray->size2();
}
else if(new_m <0)//precede begin(),and restrict to begin()
{
m=0;
n=0;
}
else
{
m = new_m;
n = new_n;
}
return *this;
}
self operator + (difference_type n)const
{
self temp = *this;
return temp += n;
}
self& operator -= (difference_type n)
{
return *this += -n;
}
self& operator - (difference_type n)
{
self temp = *this;
return temp -= n;
}
bool operator<(const self& x)const
{
if(m<x.m) return true;
else if(m==x.m && n<x.n) return true;
else return false;
}
};
//a 2-dimension array
template <class T>
class array2
{
public:
typedef T value_type;
typedef __M_array2_iterator<T,T&,T*> iterator;
typedef __M_array2_iterator<T,const T&,const T*> const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
private:
//Array Index Out Of Bounds Exception
struct ArrayIndexOutOfBoundsException : public std::exception
{
ArrayIndexOutOfBoundsException(const char *const& what):exception(what){}
};
//a proxy class that represents a 1-dimension array
class array1
{
public:
array1():m_ptr(0) , m_size(0){}
~array1()
{
if(m_ptr)
{
delete[] m_ptr;
m_ptr=0;
}
}
//initialize
void init(size_type N)
{
//delete []m_ptr;
m_ptr = new T[N];
m_size = N;
}
array1(const array1&);//ban copy ctor
array1& operator=(const array1&);//ban assignment
reference operator [](size_type N){return m_ptr[N];}
const_reference operator [](size_type N) const{return m_ptr[N];}
size_type size() const{return m_size;}
private:
T* m_ptr;
size_type m_size;
};
private:
array1* m_pCon;
size_type m_size;
//bounds check
void _M_init_proxys(size_type M,size_type N)
{
for(size_type i=0 ; i<M ; ++i)
m_pCon[i].init(N);
}
void _M_bounds_check(size_type M,size_type N) const
{
if(M >= m_size && N>=m_pCon[0].size())
throw ArrayIndexOutOfBoundsException("Array Index Out Of Bounds");
}
public:
array2():m_pCon(0),m_size(0){}
array2(size_type M, size_type N):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
}
~array2()
{
if(m_pCon && m_size)
{
delete[] m_pCon;
m_pCon=0;
}
}
array2(size_type M , size_type N , array2<T>& a):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
difference_type num2 = a.size();
difference_type num1 = M*N;
std::copy(a.begin(), (num1>=num2)?a.end():(a.begin()+num1) ,begin());
}
array2(size_type M , size_type N , iterator f , iterator l):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
difference_type num2 = std::distance(f,l);
difference_type num1 = M*N;
std::copy(f, (num1>=num2)?l:(f+num1) ,begin());
}
array2(const array2<T>& a)
{
m_pCon = new array1[a.m_size];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.m_pCon[0].size());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=a[i][j];
}
m_size=a.m_size;
}
array2<T>& operator = (const array2<T>& a)
{
if(&a != this)
{
delete []m_pCon;
m_pCon = new array1[a.m_size];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.m_pCon[0].size());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=a[i][j];
}
m_size=a.m_size;
}
return *this;
}
//retrieve the total size
size_type size()const
{return size1()*size2();}
//retrieve the first dimension's size
size_type size1()const
{return m_size;}
//retrieve the second dimension's size
size_type size2()const
{return m_pCon[0].size();}
//resize the array and keep the previous content in the array
void resize(size_type m,size_type n)
{
array1* newPlace=new array1[m];
for(size_type i=0 ; i<m ; ++i)
newPlace[i].init(n);
for(size_type i=0 ; i<std::min(m,m_size) ; ++i)
for(size_type j=0 ; j<std::min(n,m_pCon[0].size()) ; ++j)
newPlace[i][j] = m_pCon[i][j];
delete [] m_pCon;
m_pCon = newPlace;
m_size = m;
}
array1& operator [] (size_type m){return m_pCon[m];}
const array1& operator [] (size_type m) const{return m_pCon[m];}
reference at(size_type m,size_type n) { _M_bounds_check(m,n); return m_pCon[m][n]; }
const_reference at(size_type m,size_type n) const { _M_bounds_check(m,n); return m_pCon[m][n]; }
void assign (const_reference value)
{
std::fill_n(begin(),size(),value);
}
void swap(array2<T>& y)
{
std::swap(m_pCon , y.m_pCon);
std::swap(m_size , y.m_size);
}
iterator begin() { return iterator(0,0,this); }
const_iterator begin() const { return const_iterator(0,0,this); }
iterator end() { return iterator(size1()-1,size2(),this); }
const_iterator end() const { return const_iterator(size1()-1,size2(),this); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
reference front() { return at(0,0); }
const_reference front() const {return at(0,0);}
reference back() { return at(size1()-1,size2()-1); }
const_reference back() const { return at(size1()-1,size2()-1); }
//member templates
template <class T2>
array2(const array2<T2>& a)
{
m_pCon = new array1[a.size1()];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.size2());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=static_cast<T>(a[i][j]);
}
m_size=a.size1();
}
template <class T2>
array2<T>& operator = (const array2<T2>& a)
{
delete []m_pCon;
m_pCon = new array1[a.size1()];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.size2());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=static_cast<T>(a[i][j]);
}
m_size=a.size1();
return *this;
}
template <class T2>
void swap(array2<T2>& y)
{
//unfinished
}
template<class InputIterator>
array2(size_type M , size_type N , InputIterator f , InputIterator l):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
difference_type num2 = std::distance(f,l);
difference_type num1 = M*N;
std::copy(f, (num1>=num2)?l:(f+num1) ,begin());
}
};
//relative global comparison functiaon
template<class T>
bool operator== (const array2<T>& x, const array2<T>& y)
{
if(x.size1() != y.size1() || x.size2() != y.size2() ) return false;
array2<T>* px = const_cast< array2<T>* >(&x);
array2<T>* py = const_cast< array2<T>* >(&y);
return std::equal (px->begin(), px->end(), py->begin());
}
template<class T>
bool operator< (const array2<T>& x, const array2<T>& y)
{
array2<T>* px = const_cast< array2<T>* >(&x);
array2<T>* py = const_cast< array2<T>* >(&y);
return std::lexicographical_compare(px->begin(),px->end(),py->begin(),py->end());
}
template<class T>
bool operator!= (const array2<T>& x, const array2<T>& y) {return !(x==y);}
template<class T>
bool operator> (const array2<T>& x, const array2<T>& y) {return y<x;}
template<class T>
bool operator<= (const array2<T>& x, const array2<T>& y) {return !(y<x);}
template<class T>
bool operator>= (const array2<T>& x, const array2<T>& y) {return !(x<y);}
// global swap()
template<class T>
inline void swap (array2<T>& x, array2<T>& y) {x.swap(y);}
}//end of namespace kimi_boost
#endif//__KIMI_BOOST_ARRAY2
接下来是例子程序
void array2_test()
{
kimi_boost::array2<float> f3(2,3);
kimi_boost::array2<float> f4(3,4);
f3[0][0]=456.3f;
f3[0][1]=46.9f;
f3[0][2]=45.9f;
f3[1][0]=-17.5f;
f3[1][1]=0.0f;
f3[1][2]=1.0f;
kimi_boost::array2<float> f10(3,2,f3.begin(),f3.end());
std::copy(f10.begin(),f10.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
kimi_boost::array2<float> f11(3,5,f3);
std::copy(f11.begin(),f11.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
//f3[1] = f3[0]; //error
kimi_boost::array2<float> f1(f3);
kimi_boost::array2<float> f2;
f2=f3;
f4.assign(9.0f);
f3.swap(f4);
f3.swap(f4);
std::copy(f3.begin(),f3.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
std::sort(f3.begin(),f3.end());
std::copy(f3.begin(),f3.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
std::copy(f3.rbegin(),f3.rend(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
kimi_boost::array2<float> f6(f3);
std::cout<< (f6==f3) <<"\r\n";
std::cout<< (f6<f3) <<"\r\n";
f6[0][0]=666.666f;
std::cout<< (f6==f3) <<"\r\n";
std::cout<< (f3<f6) <<"\r\n";
vector<int> vi;
vi.assign(10,666);
kimi_boost::array2<int> ai(2,5,vi.begin(),vi.end());
std::copy(ai.begin(),ai.end(),std::ostream_iterator<int>(std::cout," "));
std::cout<<"\r\n";
}
不足之处多多
欢迎拍砖
发表评论
-
The Elements of Programing Style
2009-08-09 18:26 1269把代码写清楚,别耍小聪明。 想干什么,讲的简单点、直接点。 只 ... -
6个变态的C语言Hello World程序
2009-06-01 09:37 807转载自:http://cocre.com/?p=914 下面 ... -
在VS2005中使用IBM Purify的注意事项
2009-05-12 12:24 3999Rational Purify 使用及分析实例可以见这里htt ... -
boost.pool源码整理和使用说明
2007-07-22 13:49 270Source #ifndef __KIMI_BOOST_PO ... -
boost.any源码整理和使用说明
2007-08-24 22:44 2090Source #include <algorithm& ... -
boost.array源码整理和使用说明
2007-08-24 22:45 1293Source #include <cstddef> ... -
boost.BOOST_STATIC_ASSERT源码整理和使用说明
2007-08-24 22:49 1364Source #include <boost/conf ... -
boost.shared_ptr源码整理和使用说明
2007-08-24 22:51 4189Source #pragma once //share ... -
boost.lexical_cast源码整理和使用说明
2007-08-24 22:55 1543Source #include <cstddef> ... -
编译期判断类的继承性
2007-08-24 23:00 1109介绍一个雕虫小技:编译期判断类的继承性。具体来说就是类型U是否 ... -
boost.type_traits源码整理和使用说明(1)
2007-08-28 01:35 2079Introduction The Boost type-tr ... -
泛型快速排序
2007-08-28 03:20 945Source #ifndef kimi_quicksort ... -
C++ Meta Programming 和 Boost MPL(1)
2007-08-30 23:01 1605本系列全部转载自kuibyshev.bokee.com ... -
C++ Meta Programming 和 Boost MPL(2)
2007-08-30 23:02 1536本系列全部转载自kuibyshev.bokee.com ... -
C++ Meta Programming 和 Boost MPL(3)
2007-08-30 23:06 1527本系列全部转载自kuibyshev.bokee.com ... -
C++ Meta Programming 和 Boost MPL(4)
2007-08-30 23:07 1706本系列全部转载自kuibyshev.bokee.com ... -
泛型归并排序
2007-09-18 00:23 1213#define SENTINEL_CARD (-1) # ... -
泛型插入排序
2007-09-18 00:25 1210#pragma once #include <iter ... -
boost.tuple源码整理和使用说明
2007-10-07 23:13 1597Introduction A tuple (or n-tup ... -
才发现VC中也可以检测内存泄漏
2009-03-30 14:54 1379#include <stdio.h> ...
相关推荐
### CStringArray 与 二维数组应用详解 在深入探讨 `CStringArray` 与二维数组的应用之前,我们首先简要了解一下 `CStringArray` 和其在 C++ 中的基本概念。 #### 一、CStringArray 概述 `CStringArray` 是 MFC...
首先,让我们了解鞍点的定义:在一个二维数组(矩阵)中,如果某元素的值是其所在行的最大值,并且是其所在列的最小值,那么这个元素就被称为鞍点。例如,对于以下二维数组: ``` 1 2 3 4 5 6 7 8 9 ``` 在这个...
二维数组通常被用来模拟网格或表格数据结构,而`std::vector` 提供了比传统C风格二维数组更方便和安全的管理方式。 首先,让我们了解`std::vector`的基本用法。`std::vector` 是一个模板类,可以存储任何类型的对象...
- **容器嵌套**:容器可以嵌套使用,例如在一个`std::vector<std::vector<int>>`中存储二维数组。 - **异常安全**:当处理大量数据时,确保代码具备良好的异常安全性是非常重要的。 #### 四、实践示例 下面是一个...
而C语言虽然没有内置的数据结构,但可以通过定义二维数组实现,代码风格更加底层,对内存管理有更直接的控制。 总结来说,0-1背包问题是动态规划的经典应用,它锻炼了我们分解问题、构建状态转移方程和优化算法的...
9. **数组函数的应用**:如何使用STL中的`std::sort`对数组进行排序,以及`std::copy`将数组元素复制到另一个数组或容器。 通过这些练习,你将能深入理解C++中的字符串和数组,从而提高你的编程能力。同时,如果...
在本程序中,开发者通过创建一个二维数组来模拟迷宫环境,并通过算法设计解决迷宫问题。以下将详细介绍相关知识点: 1. **C++语言基础**:C++是面向对象的编程语言,具有高效、灵活和强大的特性。编写迷宫程序需要...
在C++代码中,通常会定义一个二维数组来表示细胞的状态,每个数组元素对应一个细胞,值为1表示存活,0表示死亡。初始化时,可以根据随机数或者预设的模式设置细胞状态。 接着,生命游戏的规则如下: 1. 如果一个...
5. **lesson 5** - 可能涵盖了数组和动态数组的使用,包括一维数组、二维数组以及使用vector和dynamic_array等STL容器进行动态内存管理。 6. **lesson 6** - 可能讲解了字符串处理,包括C风格的字符串和C++标准库中...
- 动态行数的二维`vector`:`Array.push_back(line)`用于在`vector`的末尾添加一个新的`vector`行,然后逐个插入元素。 3. **`remove_if()`算法**: - `remove_if()`是STL中的一种条件删除算法,它接受一个迭代器...
13. 陷阱:计算一个二维数组中能装下的雨水量。 14. 旋转图像:将矩阵顺时针或逆时针旋转90度。 15. 加一:在给定的非负整数数组表示的数上加一,考虑进位情况。 16. 爬楼梯:模拟爬楼梯过程,使用动态规划求解最小...
3. **数组**:数组是存储相同类型元素的集合,练习可能包含一维数组、二维数组的操作,如初始化、遍历、排序等。 4. **指针**:C++的指针是其强大的特性之一,用于存储内存地址。练习可能包括指针的声明、使用指针...
2. 螺旋队列:螺旋队列是一种数据结构,结合了队列的先进先出(FIFO)特性与数组的线性存储方式,通常用于解决特定的算法问题,如二维数组的螺旋遍历。`螺旋队列.cpp`可能涉及如何实现这种数据结构及其应用。 3. 宏...
2. 二维数组或动态数组:固定宽度的块存储,便于内存管理和并行计算。 3. 位向量:使用位操作,节省空间,但可能增加复杂性。 接下来是实现基本运算。大整数的加法和减法相对简单,只需逐位进行,考虑进位或借位...
邻接矩阵是二维数组,存储图中每对顶点之间是否存在边;邻接表则更为节省空间,只存储实际存在的边。在这个课程设计中,C++的STL(标准模板库)提供了方便的数据结构如`vector`和`list`,可以用来实现邻接表。 3. *...
5. **数组与动态内存**:理解数组的使用,包括一维、二维数组,以及动态内存分配(如new和delete操作)。 6. **预处理器宏**:预处理器是编译过程的一部分,考生应了解宏定义、条件编译指令等。 7. **标准库的使用...
4. **数组和指针**:深入理解数组的使用,包括一维、二维数组,以及指针的声明、赋值、操作,以及指针与数组的关系。 5. **字符串**:介绍C++中的字符串处理,如C风格的字符数组和C++标准库中的std::string。 6. *...
5. **数组与指针**:一维、二维数组的操作,指针的概念,指针运算,动态内存管理(malloc、free)。 6. **容器**:虽然二级考试可能不涉及STL(标准模板库),但数组和指针作为基础,是理解容器(如vector、list、...
在上面的代码中,我们定义了一个二维 vector `Array`,其中每个元素也是一个 vector。我们首先使用 `push_back` 函数将 0 到 8 的整数依次添加到每个子 vector 中,然后使用 `size` 函数获取每个子 vector 的大小,...
- 一维、二维数组的声明、初始化和操作。 - 字符串的处理,包括标准库中的string类以及C风格的字符数组。 4. **结构体与联合体**: - 结构体的定义和使用,包括结构体数组和结构体指针。 - 联合体的理解及在...