"《算法导论》之‘线性表’":基于动态分配的数组的顺序表
我们利用静态分配的数组来实现的顺序表的局限还是挺大的,主要在于它的容量是预先定好的,用户不能根据自己的需要来改变。如果为了后续用户能够自己调整顺序表的大小,动态地分配数组空间还是很有必要的。基于动态分配的数组的顺序表绝大部分跟基于静态分配的数组的顺序表是一样的,只需在后者程序上改动一小部分即可。
第一,我们不需定义一个容量常量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/.
"《算法导论》之‘线性表’":基于动态分配的数组的顺序表的更多相关文章
- "《算法导论》之‘线性表’":基于静态分配的数组的顺序表
首先,我们来搞明白几个概念吧(参考自网站数据结构及百度百科). 线性表 线性表是最基本.最简单.也是最常用的一种数据结构.线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外, ...
- C++利用动态数组实现顺序表(不限数据类型)
通过类模板实现顺序表时,若进行比较和遍历操作,模板元素可以通过STL中的equal_to仿函数实现,或者通过回调函数实现.若进行复制操作,可以采用STL的算法函数,也可以通过操作地址实现.关于回调函数 ...
- C语言利用动态数组实现顺序表(不限数据类型)
实现任意数据类型的顺序表的初始化,插入,删除(按值删除:按位置删除),销毁功能.. 顺序表结构体 实现顺序表结构体的三个要素:(1)数组首地址:(2)数组的大小:(3)当前数组元素的个数. //顺序表 ...
- 使用JAVA数组实现顺序表
1,引入了JAVA泛型类,因此定义了一个Object[] 类型的数组,从而可以保存各种不同类型的对象. 2,默认构造方法创建了一个默认大小为16的Object数组:带参数的构造方法创建一个指定长度的O ...
- 《算法导论》习题解答 Chapter 22.1-8(变换邻接表的数据结构)
一般散列表都与B+树进行比较,包括在信息检索中也是. 确定某条边是否存在需要O(1). 不足: (1)散列冲突. (2)哈希函数需要不断变化以适应需求. 另外:B+树.(见第18章) 与散列表相比的不 ...
- $Django 多对多-自定义第三张表 基于双下划线的跨表查询(补充)
自定义第三张表的好处:可以定义多个字段, 缺点:查询不方便(有方法解决) 1.第三张表设置外键,联合唯一(查询不方便) class Books(models.Model): name=models.C ...
- YTU 2989: 顺序表基本运算(线性表)
2989: 顺序表基本运算(线性表) 时间限制: 1 Sec 内存限制: 128 MB 提交: 1 解决: 1 题目描述 编写一个程序,实现顺序表的各种基本运算(假设顺序表的元素类型为char), ...
- C# 数据结构 线性表(顺序表 链表 IList 数组)
线性表 线性表是最简单.最基本.最常用的数据结构.数据元素 1 对 1的关系,这种关系是位置关系. 特点 (1)第一个元素和最后一个元素前后是没有数据元素,线性表中剩下的元素是近邻的,前后都有元素. ...
- 基于C++的顺序表的实现
顺序表,是数据结构中按顺序方式存储的线性表,又称向量.具有方便检索的特点.以下,是笔者学习是基于C++实现的顺序表代码,贴上来当网页笔记用. #include <iostream> usi ...
随机推荐
- Not saving crash log because we have reached the limit for logs to store on disk.解决办法
一.问题简述: Xcode, window>Devices>DEVICES选中自已的设备,打开控制台:提示日志存量已达限制,这个是系统抛出的log."Not saving cra ...
- Memcached - In Action
Memcached 标签 : Java与NoSQL With Java 比较知名的Java Memcached客户端有三款:Java-Memcached-Client.XMemcached以及Spym ...
- 【伯乐在线】最值得阅读学习的 10 个 C 语言开源项目代码
原文出处: 平凡之路的博客 欢迎分享原创到伯乐头条 伯乐在线注:『阅读优秀代码是提高开发人员修为的一种捷径』http://t.cn/S4RGEz .之前@伯乐头条 曾发过一条微博:『C 语言进阶有 ...
- zookeeper分布式部署方案
版本:http://apache.fayea.com/zookeeper/zookeeper-3.4.8/环境:debian 7/8说明:最低配置3台步骤:1.下载zookeeper-3.4.8并解压 ...
- win8如何共享文件夹
最近小编接手了市委组织部考核项目,各种文档.ER图.原型图,组员之间需要拷来拷去,很不方便,通过飞信,QQ传输吧,文件太大,网络太慢,所以还是不行,于是小编就想起来要共享,以前也映射过别人的共享,觉得 ...
- Swift函数柯里化(Currying)简谈
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化.简单的说就是把接收多 ...
- 6.4、Android Studio的GPU Monitor
Android Monitor包含GPU Monitor,它将可视化的显示渲染窗体的时间.GPU Monitor可以帮助你: 1. 迅速查看UI窗体生成 2. 辨别是否渲染管道超出使用线程时间 在GP ...
- (一一九)通过CALayer实现阴影、圆角、边框和3D变换
在每个View上都有一个CALayer作为父图层,View的内容作为子层显示,通过layer的contents属性决定了要显示的内容,通过修改过layer的一些属性可以实现一些华丽的效果. [阴影和圆 ...
- 编译GDAL支持MySQL
GDAL支持MySQL需要MySQL的库才可以,编译很简单,修改nmake.opt文件中对应的MySQL的库的路径和lib即可. nmake.opt文件中397行左右,如下: # MySQL Libr ...
- 06_NoSQL数据库之Redis数据库:Redis的高级应用之登录授权和主从复制
Redis高级实用特征 安全性(登录授权和登录后使用auth授权) 设置客户端连接后进行任何其他指定前需要使用的密码. 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户 ...