我们利用静态分配的数组来实现的顺序表的局限还是挺大的,主要在于它的容量是预先定好的,用户不能根据自己的需要来改变。如果为了后续用户能够自己调整顺序表的大小,动态地分配数组空间还是很有必要的。基于动态分配的数组的顺序表绝大部分跟基于静态分配的数组的顺序表是一样的,只需在后者程序上改动一小部分即可。

  第一,我们不需定义一个容量常量CAPACITY,而是定义一个私有变量myCapacity。

  第二,类的构造函数需要改进一下。我们需要类在被实例化时自动申请内存,即需添加下边程序:

ElementType * seqList = new ElementType(myCapacity);
assert(seqList != NULL);

  第三,类的析构函数需要添加下边一句:

delete [] seqList;

  上面三点说的还有所欠缺。Larry Nyhoff在《数据结构与算法分析》第253页中提到设计类时要记住的一条规则:

  如果类在运行时使用new分配内存,则它应该提供:

  • 把动态分配的内存还给堆的析构函数。
  • 编译器用来创建不同副本的复制构造函数。
  • 程序员用来创建不同副本的赋值运算符。

  基于动态分配的数组的顺序表设计的类如下:

 // seqlist.h
#ifndef SEQLIST
#define SEQLIST #include <iostream>
#include <cassert>
#include <algorithm> using namespace std; typedef int ElementType; class SeqList
{
public:
SeqList(const int maxsize = );
virtual ~SeqList();
SeqList(const SeqList& origList);                // 拷贝构造函数,记得防止浅拷贝
const SeqList& operator=(const SeqList& rightHandSide); // 重载赋值运算符,记得防止浅拷贝
bool empty() const;
void clear();
bool insert(const int pos, const ElementType val);
bool erase(const int pos);
void display() const;
bool setSeqList(const ElementType *tmpList, const int len);
int getLenOfList() const;
ElementType getItem(const int pos);
ElementType * getSeqList();                   // 保留,不推荐使用,因为在使用过程中无法进行越界检查 private:
int myCapacity;                          // 自定义顺序表容量
int lenOfList;                           // 顺序表长度
ElementType * seqList; }; #endif

  实现程序为:

 // seqlist.cpp
#include <iostream>
#include <cassert>
#include "seqlist.h" using namespace std; SeqList::SeqList(const int maxsize)
{
// initialization
lenOfList = ;
myCapacity = maxsize;
seqList = new ElementType[myCapacity];
// assert(seqList != NULL);
if (seqList == NULL)
{
cerr << "Inadequate memory to allocate stack." << endl;
throw bad_alloc();
}
} SeqList::~SeqList()
{
delete[] seqList;
} SeqList::SeqList(const SeqList& origList)
{
myCapacity = origList.myCapacity;
lenOfList = origList.lenOfList;
seqList = new ElementType[myCapacity];
// assert(seqList != NULL);
if (seqList == NULL)
{
cerr << "Inadequate memory to allocate stack." << endl;
throw bad_alloc();
}
else
{
for (int i = ; i < lenOfList; i++)
{
seqList[i] = origList.seqList[i];
}
}
} const SeqList& SeqList::operator=(const SeqList& rightHandSide)
{
// 确保不是自我赋值
if (this != &rightHandSide)
{
// 如果需要,分配一个新数组
if (myCapacity != rightHandSide.myCapacity)
{
delete[] seqList;
myCapacity = rightHandSide.myCapacity;
seqList = new ElementType[myCapacity];
// assert(seqList != NULL);
if (seqList == NULL)
{
cerr << "Inadequate memory to allocate stack." << endl;
throw bad_alloc();
}
} lenOfList = rightHandSide.lenOfList;
for (int i = ; i < lenOfList; i++)
{
seqList[i] = rightHandSide.seqList[i];
}
}
return *this;
} bool SeqList::empty() const
{
return lenOfList == ;
} void SeqList::clear()
{
lenOfList = ;
fill(seqList, seqList + myCapacity - , );
} bool SeqList::insert(const int pos, const ElementType val)
{
bool success = false;
// assert(lenOfList != CAPACITY); // 这里的assert分成两行写,是为了方便定位错误发生的地方
// assert(0 <= pos <= lenOfList);
if (lenOfList == myCapacity)
{
cerr << "No space for insertion!" << endl;
}
else if (pos < || pos > lenOfList)
{
cerr << "The position " << pos <<
" you want to insert is less than zero or exceeds the length of the list!" << endl;
throw out_of_range("throw out_of_range"); // 抛出一个越界异常
}
else
{
int tmpCount = lenOfList - pos;
for (int i = ; i < tmpCount; i++)
{
seqList[lenOfList - i] = seqList[lenOfList - i - ];
}
seqList[pos] = val;
lenOfList++;
success = true;
}
return success;
} bool SeqList::erase(const int pos)
{
bool success = false;
// assert(lenOfList != 0);
// assert(0 <= pos <= lenOfList);
if (lenOfList == )
{
cerr << "There is no elements in the list!" << endl;
}
else if (pos < || pos > lenOfList)
{
cerr << "The position " << pos <<
" you want to erase is less than zero or exceeds the length of the list!" << endl;
throw out_of_range("throw out_of_range"); // 抛出一个越界异常
}
else
{
int tmp = lenOfList - pos;
for (int i = ; i < tmp - ; i++)
{
seqList[pos + i] = seqList[pos + i + ];
}
seqList[lenOfList - ] = ;
lenOfList--;
success = true;
}
return success;
} void SeqList::display() const
{
cout << "***Start Displaying***" << endl;
if (lenOfList == )
{
cerr << "There is no element in the the list!" << endl;
}
else
{
for (int i = ; i < lenOfList; i++)
{
cout << i << " : " << seqList[i] << endl;
}
cout << "***End Displaying***" << endl;
}
} bool SeqList::setSeqList(const ElementType *tmpList, const int len)
{
// assert(len <= CAPACITY);
bool success = false;
if (len <= myCapacity)
{
for (int i = ; i < len; i++)
{
seqList[i] = *(tmpList++);
}
lenOfList = len;
success = true;
}
else
{
cerr << "The length of the array you set exceeds the CAPACITY." << endl;
throw out_of_range("throw out_of_range"); // 抛出一个越界异常
}
return success;
} int SeqList::getLenOfList() const
{
return lenOfList;
} ElementType SeqList::getItem(const int pos)
{
// assert(0 <= pos <= lenOfList);
if (pos < || pos > lenOfList)
{
cerr << "The item at " << pos << " you want to get does not exist!" << endl;
throw out_of_range("throw out_of_range"); // 抛出一个越界异常
}
else
{
return seqList[pos];
}
} ElementType * SeqList::getSeqList()
{
return seqList;
}

seqlist.cpp

  Boost单元测试程序为:

 // BoostUnitTest.cpp
#define BOOST_TEST_MODULE ArrayList_Test_Module #include "stdafx.h"
#include "D:\VSProject\Algorithm\List\SeqList\SeqList_BsedOnDynamicArray\SeqList\seqlist.h" struct ArrayList_Fixture
{
ArrayList_Fixture()
{
BOOST_TEST_MESSAGE("Setup fixture");
testArrayList = new SeqList();
}
~ArrayList_Fixture()
{
BOOST_TEST_MESSAGE("Teardown fixture");
delete testArrayList;
} SeqList * testArrayList;
}; // BOOST_AUTO_TEST_SUITE(ArrayList_Test_Suite)
BOOST_FIXTURE_TEST_SUITE(ArrayList_Test_Suite, ArrayList_Fixture) BOOST_AUTO_TEST_CASE(ArrayList_Abnormal_Test)
{
// Set values to the array list
int testArray[] = { , , , , }; // 5 个元素
int testLenOfList = sizeof(testArray) / sizeof(int);
testArrayList->setSeqList(testArray, testLenOfList);
// BOOST_REQUIRE_THROW(testArrayList->setArrayList(testArray, testLenOfList), out_of_range); // Method getItem-----------------------------------------------
// If the position of the item you want to get is less than zero
BOOST_REQUIRE_THROW(testArrayList->getItem(-), out_of_range);
// If the position of the item you want to get is larger than the length of the list
BOOST_REQUIRE_THROW(testArrayList->getItem(), out_of_range); // Method insert-------------------------------------------------
// If the inserting position is less than zero
BOOST_REQUIRE_THROW(testArrayList->insert(-, ), out_of_range);
BOOST_REQUIRE(testArrayList->getLenOfList() == testLenOfList); // If the inserting position is larger than the length of the list
BOOST_REQUIRE_THROW(testArrayList->insert(, ), out_of_range);
BOOST_REQUIRE(testArrayList->getLenOfList() == testLenOfList); // Method erase-------------------------------------------------
// If the erasing position is less than zero
BOOST_REQUIRE_THROW(testArrayList->erase(-), out_of_range);
BOOST_REQUIRE(testArrayList->getLenOfList() == testLenOfList); // If the erasing position is larger than the length of the list
BOOST_REQUIRE_THROW(testArrayList->erase(), out_of_range);
BOOST_REQUIRE(testArrayList->getLenOfList() == testLenOfList); } BOOST_AUTO_TEST_CASE(ArrayList_Normal_Test)
{
bool expected;
bool actual;
// Method empty-------------------------------------------------
expected = true;
actual = testArrayList->empty();
BOOST_REQUIRE(expected == actual); // Set values to the array list
int testArray[] = { , , , , }; // 5 个元素
int testLenOfList = sizeof(testArray) / sizeof(int);
testArrayList->setSeqList(testArray, testLenOfList);
// BOOST_REQUIRE_THROW(testArrayList->setArrayList(testArray, testLenOfList), out_of_range); // Method getItem-----------------------------------------------
BOOST_REQUIRE(testArrayList->getItem() == testArray[]); // Method empty-------------------------------------------------
expected = false;
actual = testArrayList->empty();
BOOST_REQUIRE(expected == actual); // Method insert-------------------------------------------------
expected = true;
actual = testArrayList->insert(, );
BOOST_REQUIRE(expected == actual);
BOOST_REQUIRE(testArrayList->getLenOfList() == testLenOfList + );
BOOST_REQUIRE(testArrayList->getItem() == ); // Method erase-------------------------------------------------
expected = true;
actual = testArrayList->erase();
BOOST_REQUIRE(expected, actual);
BOOST_REQUIRE(testArrayList->getLenOfList() == testLenOfList);
BOOST_REQUIRE(testArrayList->getItem() == testArray[]); } BOOST_AUTO_TEST_CASE(ArrayList_CopyConstructor_Test)
{
bool expected;
bool actual;
// Set values to the array list
int testArray[] = { , , , , }; // 5 个元素
int testLenOfList = sizeof(testArray) / sizeof(int);
testArrayList->setSeqList(testArray, testLenOfList);
// BOOST_REQUIRE_THROW(testArrayList->setArrayList(testArray, testLenOfList), out_of_range); // Copy constructor
//SeqList * copySeqList(testArrayList); // 极容易写成这样子。错误。
// 需要给copySeqList分配内存
SeqList * copySeqList = new SeqList(*testArrayList); // Method getItem-----------------------------------------------
BOOST_REQUIRE(copySeqList->getItem() == testArray[]); // Method empty-------------------------------------------------
expected = false;
actual = copySeqList->empty();
BOOST_REQUIRE(expected == actual); // Method insert-------------------------------------------------
expected = true;
actual = copySeqList->insert(, );
BOOST_REQUIRE(expected == actual);
BOOST_REQUIRE(copySeqList->getLenOfList() == testLenOfList + );
BOOST_REQUIRE(copySeqList->getItem() == ); // Method erase-------------------------------------------------
expected = true;
actual = copySeqList->erase();
BOOST_REQUIRE(expected, actual);
BOOST_REQUIRE(copySeqList->getLenOfList() == testLenOfList);
BOOST_REQUIRE(copySeqList->getItem() == testArray[]);
} BOOST_AUTO_TEST_CASE(ArrayList_EqualOperator_Test)
{
bool expected;
bool actual;
// Set values to the array list
int testArray[] = { , , , , }; // 5 个元素
int testLenOfList = sizeof(testArray) / sizeof(int);
testArrayList->setSeqList(testArray, testLenOfList);
// BOOST_REQUIRE_THROW(testArrayList->setArrayList(testArray, testLenOfList), out_of_range); // Copy constructor
SeqList * copySeqList = new SeqList();
// copySeqList = testArrayList; // 极易犯的一个低级错误
*copySeqList = *testArrayList; // Method getItem-----------------------------------------------
BOOST_REQUIRE(copySeqList->getItem() == testArray[]); // Method empty-------------------------------------------------
expected = false;
actual = copySeqList->empty();
BOOST_REQUIRE(expected == actual); // Method insert-------------------------------------------------
expected = true;
actual = copySeqList->insert(, );
BOOST_REQUIRE(expected == actual);
BOOST_REQUIRE(copySeqList->getLenOfList() == testLenOfList + );
BOOST_REQUIRE(copySeqList->getItem() == ); // Method erase-------------------------------------------------
expected = true;
actual = copySeqList->erase();
BOOST_REQUIRE(expected, actual);
BOOST_REQUIRE(copySeqList->getLenOfList() == testLenOfList);
BOOST_REQUIRE(copySeqList->getItem() == testArray[]);
} BOOST_AUTO_TEST_SUITE_END();

BoostUnitTest.cpp

  本篇博文的代码均托管到Taocode : http://code.taobao.org/p/datastructureandalgorithm/src/.

"《算法导论》之‘线性表’":基于动态分配的数组的顺序表的更多相关文章

  1. "《算法导论》之‘线性表’":基于静态分配的数组的顺序表

    首先,我们来搞明白几个概念吧(参考自网站数据结构及百度百科). 线性表 线性表是最基本.最简单.也是最常用的一种数据结构.线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外, ...

  2. C++利用动态数组实现顺序表(不限数据类型)

    通过类模板实现顺序表时,若进行比较和遍历操作,模板元素可以通过STL中的equal_to仿函数实现,或者通过回调函数实现.若进行复制操作,可以采用STL的算法函数,也可以通过操作地址实现.关于回调函数 ...

  3. C语言利用动态数组实现顺序表(不限数据类型)

    实现任意数据类型的顺序表的初始化,插入,删除(按值删除:按位置删除),销毁功能.. 顺序表结构体 实现顺序表结构体的三个要素:(1)数组首地址:(2)数组的大小:(3)当前数组元素的个数. //顺序表 ...

  4. 使用JAVA数组实现顺序表

    1,引入了JAVA泛型类,因此定义了一个Object[] 类型的数组,从而可以保存各种不同类型的对象. 2,默认构造方法创建了一个默认大小为16的Object数组:带参数的构造方法创建一个指定长度的O ...

  5. 《算法导论》习题解答 Chapter 22.1-8(变换邻接表的数据结构)

    一般散列表都与B+树进行比较,包括在信息检索中也是. 确定某条边是否存在需要O(1). 不足: (1)散列冲突. (2)哈希函数需要不断变化以适应需求. 另外:B+树.(见第18章) 与散列表相比的不 ...

  6. $Django 多对多-自定义第三张表 基于双下划线的跨表查询(补充)

    自定义第三张表的好处:可以定义多个字段, 缺点:查询不方便(有方法解决) 1.第三张表设置外键,联合唯一(查询不方便) class Books(models.Model): name=models.C ...

  7. YTU 2989: 顺序表基本运算(线性表)

    2989: 顺序表基本运算(线性表) 时间限制: 1 Sec  内存限制: 128 MB 提交: 1  解决: 1 题目描述 编写一个程序,实现顺序表的各种基本运算(假设顺序表的元素类型为char), ...

  8. C# 数据结构 线性表(顺序表 链表 IList 数组)

    线性表 线性表是最简单.最基本.最常用的数据结构.数据元素 1 对 1的关系,这种关系是位置关系. 特点 (1)第一个元素和最后一个元素前后是没有数据元素,线性表中剩下的元素是近邻的,前后都有元素. ...

  9. 基于C++的顺序表的实现

    顺序表,是数据结构中按顺序方式存储的线性表,又称向量.具有方便检索的特点.以下,是笔者学习是基于C++实现的顺序表代码,贴上来当网页笔记用. #include <iostream> usi ...

随机推荐

  1. tomcat自动运行磁盘任意位置上的项目、使用Maven对tomcat进行自动部署

     对于非Maven的web项目,有时候我们想不时常通过打war包.拷贝war包.启动tomcat来运行项目.这时候我们可以通过以下方式来进行配置: 1.1:创建web工程.工程结构如下: 1.2. ...

  2. Java学习之继承中的执行顺序详解

    代码块(理解) (1)用{}括起来的代码. (2)分类: A:局部代码块 用于限定变量的生命周期,及早释放,提高内存利用率. B:构造代码块 把多个构造方法中相同的代码可以放到这里,每个构造方法执行前 ...

  3. Dynamics CRM 站点地图中URL的&号编码问题

    现在大多数人对站点地图的操作都通过工具来执行,但如果你使用原始的编辑XML方式,并且你的SubArea中对应的不是某个Entity而是一串URL时,要注意了你的URL中如果带有与符号即&,那就 ...

  4. Spring入门介绍(一)

    Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架,它主要是为了解决企业应用开发的复杂性而诞生的. 目的:解决企业应用开发的复杂性. 功能:使用基本的javaBean代替EJB. ...

  5. Android打包遇到的那些坑

    说说今天打包遇到的坑,由于线上有个支付的bug需要紧急修复,而我们的项目又没有使用热修复,所以只能通过编译打包等传统流程,还好android上线比较快. 说说我进早上打包遇到的几个问题吧,首先我使用b ...

  6. javascript之正则表达式

    创建正则表达式的两种方法 显式: new RegExp("pattern"[,"flags"]); 例 var regex = new ("abc&q ...

  7. 对 jiffies 溢出、回绕及 time_after 宏的理解

    原文如下: 关于jiffies变量:     全局变量jiffies用来记录自启动以来产生的节拍的总数.系统启动时会将该变量初始化为0,此后,每当时钟中断产生时就会增加该变量的值.jiffies和另外 ...

  8. java中hashCode()与equals()详解

    首先之所以会将hashCode()与equals()放到一起是因为它们具备一个相同的作用:用来比较某个东西.其中hashCode()主要是用在hash表中提高 查找效率,而equals()则相对而言使 ...

  9. [C]simple code of count input lines,words,chars

    This is a simple C program which can count input lines, words and chars. But the number of words are ...

  10. Java中封装性的使用

    //Java面对对象基本特性之一:封装性 //作用:保护某些属性和方法不被外部所看见 //封装的实现:通过关键字private声明 //鼠标右键--->Source---->Generat ...