上一篇文章实现了List和SeqList,本篇分析两个子类StaticList和DynamicList是怎么实现的。
StaticList
实现StaticList要点:
1、使用原生数组作为顺序存储空间;
2、使用模板参数决定数组大小;
代码:
#ifndef _STATICLIST_H_
#define _STATICLIST_H_
#include "SeqList.h"
namespace DTLib
{
template < typename T, int N >
class StaticList :public SeqList<T>
{
protected:
T m_space[N]; // 顺序存储空间,N为模板参数
public:
StaticList() // 指定父类成员的具体值
{
this->m_array = m_space;
this->m_length = 0;
}
int capacity() const
{
return N;
}
};
}
#endif
DynamicList
实现DynamicList要点:
1、申请连续内存作为顺序存储空间。存储空间是new出来的,不同于StaticList使用原生数组;
2、动态设置顺序存储空间的大小;
3、保证重置顺序存储空间时的异常安全性;
#ifndef _DYNAMICLIST_H_
#define _DYNAMICLIST_H_
#include "SeqList.h"
namespace DTLib
{
template <typename T>
class DynamicList : public SeqList<T>
{
protected:
int m_capicity; // 顺序存储空间的大小
public:
DynamicList(int capacity) // 在堆空间申请空间
{
this->m_array = new T[capacity];
if (this->m_array != NULL)
{
this->m_length = 0;
this->m_capicity = capacity;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memery to create DynamicList object ...");
}
}
int capacity() const
{
return m_capicity;
}
void resize(int capacity)
{
if (capacity != m_capicity)
{
T* array = new T[capacity]; // 不直接操作m_array,而是定义局部指针
if (array != NULL)
{
int length = (this->m_length < capacity ? this->m_length : capacity);
for (int i = 0; i < length; i++) // 复制数据元素到新申请的空间,保证原来的数据不丢失
{
array[i] = this->m_array[i];
}
T* temp = this->m_array;
this->m_array = array; // 更新m_array
this->m_length = length;
this->m_capicity = capacity;
delete[] temp;
}
else // 申请内存失败
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memery to resize DynamicList object ...");
}
}
}
~DynamicList() // m_array在构造函数里面申请了堆空间
{
delete[] this->m_array;
}
};
}
#endif
重新设置存储空间的大小方法是:
(1)先根据capacity申请一段新的堆空间array;
(2)给array赋值,用来保存原有的数据;
(3)保存原来的堆空间的地址;
(4)将m_array指向新的堆空间(实现重置);
(5)释放原来的堆空间的地址;
至此,静态顺序表StaticList和动态顺序表DynamicList实现完毕。