数据结构是计算机专业的基础课。在学校的时候学了一遍觉得也没有什么(当然,老师说这是很重要的一门课程),在毕业设计中什么也没用上。工作快两年了,虽然还是什么也没用上,但渐渐的感觉数据结构越来越重要了。这种感觉是在潜移默化中形成的,于是重新找出课本开始温故而知新了。弹去书上的尘土随手翻看,猛然间看到了当初夹在书中的活页。上面记录着侯捷先生在《STL源码剖析》中的一段话:“作为一个程序员,如果你是做数据库编程的,大可以不懂汇编语言,如果你是写驱动程序的,大可以不必通晓人工智能,写编译器的可以不用懂什么计算机图形学,操作系统内核高手的不用精通网站架设。然而,如果你不懂数据结构与算法的基础知识,不具备数据结构与算法的基本技能,那就完全丧失成为一个程序员的资格!”。看到这,好像又回到在校时对中国软件业充满信心的那个时代。呵呵,快离校两年了,要不是见物生情在校时那种激情好像再也想不起来了。
好了,说正题。在重新复习的过程中,我把书中例子再一次的实现,有的还进行了扩展。这里把他们拿出来,供大家参考。就像读书笔记一样,不过这里还加入了我个人的一些东西,望指正。(参考:《数据结构与算法------面向对象的C++设计模式》)
在C++中提供了内嵌的数组,但是有很多缺点。比如:不能把一个数组赋给另一个数组,对数组下标不进行越界检查,在编译期间一个数组的大小是静态和固定的,除非程序员使用动态内存分配。所以,我们先来写个数组类,完善这些功能。就像MFC中的CArray类一样,当然我们写的例子不可能像Microsoft封装的那样好,然而我们可以用简单的方法来实现复杂的功能。也许它看起来很低级,运行起来会很慢,但是它的的确确是我们自己改写的。下面是这个数组类的定义,包括成员函数。
template <class T>
class Array
{
private:
T *pData;
unsigned int base;
unsigned int length;
public:
Array();
Array(Array const&);
Array(unsigned int ,unsigned int= 0);
~Array();
T const &operator [] (int) const;
T &operator [] (int);
Array &operator = (Array const&);
bool operator == (Array const&);
bool IsEmpty() const;
unsigned int GetBase() const;
unsigned int GetLength() const;
void SetLength(unsigned int,bool);
void InsertAt(unsigned int nPos, T Value);
void RemoveAt(unsigned int nPos);
};
在private域中有三个成员变量,成员pData是一个指向数组数据的指针,成员base和length用于计算数组下标。由于在C++内置的数组中下标是从0开始的,这是不可改变的。而base这个成员变量却可以帮助你修改这个规定。你可以随意设置这个变量的值,但是如果是负值或者比length大那么构造函数将按照默认值处理。
这个类对[]、=、==这三个操作符进行了重载。为的是能使这个类支持下标操作、赋值操作和比较操作。当然,可能存在好多bug,这还有待于进一步的修改。
#include <iostream>
using namespace std;
/*****************************************************************************
* Function Explain:默认构造函数
*
* Input Parameter:
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline Array<T>::Array():pData(new T[0]),base(0),length(0)
{}
/*****************************************************************************
* Function Explain:重载构造函数,自由设定base和length
*
* Input Parameter:
* Output Parameter:
* Return Values:
*****************************************************************************/
template<class T>
inline Array<T>::Array(unsigned int unLength, unsigned int unBase)
{
if((unLength < 0)||(unBase > unLength))
{
length = 0;
base = 0;
pData = new T[length];
}
else if(unBase < 0)
{
base = 0;
length = unLength;
pData = new T[length];
}
else
{
base = unBase;
length = unLength;
pData = new T[length];
}
}
/*****************************************************************************
* Function Explain:拷贝构造函数
*
* Input Parameter:
* Output Parameter:
* Return Values:
*****************************************************************************/
template<class T>
inline Array<T>::Array(Array<T> const &array):pData(new T[array.length]),base(array.base),length(array.length)
{
for(unsigned int i = 0;i < length; ++i)
{
data[i] = array.data[i];
}
}
/*****************************************************************************
* Function Explain:析构函数
*
* Input Parameter:
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline Array<T>::~Array()
{
delete []pData;
}
/*****************************************************************************
* Function Explain:返回Index起始位置
*
* Input Parameter:
* Output Parameter:
* Return Values:
*****************************************************************************/
template<class T>
inline unsigned int Array<T>::GetBase() const
{
return base;
}
/*****************************************************************************
* Function Explain:返回存储长度
*
* Input Parameter:
* Output Parameter:
* Return Values:
*****************************************************************************/
template<class T>
inline unsigned int Array<T>::GetLength() const
{
return length;
}
/*****************************************************************************
* Function Explain: 重载操作符“=”,实现两个类对象的赋值操作
*
* Input Parameter:类对象
* Output Parameter:
* Return Values:
*****************************************************************************/
template<class T>
inline Array<T> &Array<T>::operator = (const Array<T> &array)
{
Array<T> *&ptArray = const_cast<Array<T>*>(this);
try
{
if(NULL == ptArray)
{
//throw std::domain_error("Initialize Pointer First!");
ptArray = new Array<T>(array.GetLength(),array.GetBase());
}
else
{
ptArray->SetLength(array.GetLength(),false);
}
for(int i = array.GetBase(); i < array.GetLength();i++)
{
(*ptArray)[i] = array[i];
}
}
catch(exception &e)
{
cerr << "Caught: " << e.what() << endl;
}
return *const_cast<Array<T>*>(this);
}
/*****************************************************************************
* Function Explain:重载操作符“==”,实现两个类对象的比较操作
*
* Input Parameter:类对象
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline bool Array<T>::operator == (Array const &array)
{
if(this->GetLength() != array.GetLength())
{
return false;
}
Array<T> *&ptArray = const_cast<Array<T>*>(this);
for(int i = array.GetBase(), int j = ptArray->GetBase();i < array.GetLength(),
j < ptArray->GetLength();i++,j++)
{
if(array[i] != (*ptArray)[j])
{
return false;
}
}
return true;
}
/*****************************************************************************
* Function Explain:重载操作符“[ ]”,实现类对象的下标操作
*
* Input Parameter:Index位置
* Output Parameter:
* Return Values:
*****************************************************************************/
template<class T>
inline T const &Array<T>::operator [](int position) const
{
int const offset = position - base;
try
{
if((offset >= (int)length)||(offset < 0))
{
throw std::out_of_range("invalid position");
}
}
catch(exception &e)
{
cerr << "Caught: " << e.what() << endl;
}
return data [offset];
}
/*****************************************************************************
* Function Explain:重载操作符“[ ]”,实现类对象的下标操作
*
* Input Parameter:Index位置
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline T &Array<T>::operator [](int position)
{
int const offset = position - base;
try
{
if((offset >= (int)length)||(offset < 0))
{
throw std::out_of_range("invalid position");
}
}
catch(exception &e)
{
cerr << "Caught: " << e.what() << endl;
}
return pData[offset];
}
/*****************************************************************************
* Function Explain:可以重新设定类对象的存储容量
*
* Input Parameter:类对象的新长度;是否要求元素移动标志
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline void Array<T>::SetLength(unsigned int newLength, bool bFlag)
{
if(GetLength() == newLength)
{
return;
}
T *const newData = new T[newLength];
if(bFlag)
{
unsigned int const min = length < newLength ? length : newLength;
for(unsigned int i = 0; i < min; i++)
{
newData[i] = data[i];
}
}
delete []data;
data = newData;
length = newLength;
}
/*****************************************************************************
* Function Explain:判断类对象是否是空
*
* Input Parameter:
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline bool Array<T>::IsEmpty() const
{
if(0 == length)
{
return TURE;
}
else
{
return FALSE;
}
}
/*****************************************************************************
* Function Explain:在类对象中插入一个元素
*
* Input Parameter:指定Index位置;插入值
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline void Array<T>::InsertAt(unsigned int nPos, T Value)
{
if(nPos > length)
{
return;
}
int nNewLength = length + 1;
T *const pNewData = new T[nNewLength];
for(int i = 0; i < nPos - 1; i++)
{
pNewData[i] = data[i];
}
pNewData[nPos-1] = Value;
if(nPos < length)
{
for(i = nPos; i < length+1;i++)
{
pNewData[i] = data[i-1];
}
}
delete []data;
data = pNewData;
length = nNewLength;
}
/*****************************************************************************
* Function Explain:在类对象中删除一个元素
*
* Input Parameter:指定Index位置
* Output Parameter:
* Return Values:
*****************************************************************************/
template <class T>
inline void Array<T>::RemoveAt(unsigned int nPos)
{
if(nPos > length)
{
return;
}
int nNewLength = length - 1;
T *const pNewData = new T[nNewLength];
for(int i = 0; i < nPos - 1; i++)
{
pNewData[i] = pData[i];
}
for(i = nPos-1; i+1 < length; i++)
{
pNewData[i] = pData[i+1];
}
delete []pData;
pData = pNewData;
length = nNewLength;
}