我们利用静态分配的数组来实现的顺序表的局限还是挺大的,主要在于它的容量是预先定好的,用户不能根据自己的需要来改变。如果为了后续用户能够自己调整顺序表的大小,动态地分配数组空间还是很有必要的。基于动态分配的数组的顺序表绝大部分跟基于静态分配的数组的顺序表是一样的,只需在后者程序上改动一小部分即可。
第一,我们不需定义一个容量常量CAPACITY,而是定义一个私有变量myCapacity。
第二,类的构造函数需要改进一下。我们需要类在被实例化时自动申请内存,即需添加下边程序:
ElementType * seqList = new ElementType(myCapacity);
assert(seqList != NULL);
第三,类的析构函数需要添加下边一句:
delete [] seqList;
上面三点说的还有所欠缺。Larry Nyhoff在《数据结构与算法分析》第253页中提到设计类时要记住的一条规则:
如果类在运行时使用new分配内存,则它应该提供:
- 把动态分配的内存还给堆的析构函数。
- 编译器用来创建不同副本的复制构造函数。
- 程序员用来创建不同副本的赋值运算符。
基于动态分配的数组的顺序表设计的类如下:
1 // seqlist.h 2 #ifndef SEQLIST 3 #define SEQLIST 4 5 #include <iostream> 6 #include <cassert> 7 #include <algorithm> 8 9 using namespace std; 10 11 typedef int ElementType; 12 13 class SeqList 14 { 15 public: 16 SeqList(const int maxsize = 1024); 17 virtual ~SeqList(); 18 SeqList(const SeqList& origList); // 拷贝构造函数,记得防止浅拷贝 19 const SeqList& operator=(const SeqList& rightHandSide); // 重载赋值运算符,记得防止浅拷贝 20 bool empty() const; 21 void clear(); 22 bool insert(const int pos, const ElementType val); 23 bool erase(const int pos); 24 void display() const; 25 bool setSeqList(const ElementType *tmpList, const int len); 26 int getLenOfList() const; 27 ElementType getItem(const int pos); 28 ElementType * getSeqList(); // 保留,不推荐使用,因为在使用过程中无法进行越界检查 29 30 private: 31 int myCapacity; // 自定义顺序表容量 32 int lenOfList; // 顺序表长度 33 ElementType * seqList; 34 35 }; 36 37 #endif
实现程序为:
1 // seqlist.cpp 2 #include <iostream> 3 #include <cassert> 4 #include "seqlist.h" 5 6 using namespace std; 7 8 SeqList::SeqList(const int maxsize) 9 { 10 // initialization 11 lenOfList = 0; 12 myCapacity = maxsize; 13 seqList = new ElementType[myCapacity]; 14 // assert(seqList != NULL); 15 if (seqList == NULL) 16 { 17 cerr << "Inadequate memory to allocate stack." << endl; 18 throw bad_alloc(); 19 } 20 } 21 22 SeqList::~SeqList() 23 { 24 delete[] seqList; 25 } 26 27 SeqList::SeqList(const SeqList& origList) 28 { 29 myCapacity = origList.myCapacity; 30 lenOfList = origList.lenOfList; 31 seqList = new ElementType[myCapacity]; 32 // assert(seqList != NULL); 33 if (seqList == NULL) 34 { 35 cerr << "Inadequate memory to allocate stack." << endl; 36 throw bad_alloc(); 37 } 38 else 39 { 40 for (int i = 0; i < lenOfList; i++) 41 { 42 seqList[i] = origList.seqList[i]; 43 } 44 } 45 } 46 47 const SeqList& SeqList::operator=(const SeqList& rightHandSide) 48 { 49 // 确保不是自我赋值 50 if (this != &rightHandSide) 51 { 52 // 如果需要,分配一个新数组 53 if (myCapacity != rightHandSide.myCapacity) 54 { 55 delete[] seqList; 56 myCapacity = rightHandSide.myCapacity; 57 seqList = new ElementType[myCapacity]; 58 // assert(seqList != NULL); 59 if (seqList == NULL) 60 { 61 cerr << "Inadequate memory to allocate stack." << endl; 62 throw bad_alloc(); 63 } 64 } 65 66 lenOfList = rightHandSide.lenOfList; 67 for (int i = 0; i < lenOfList; i++) 68 { 69 seqList[i] = rightHandSide.seqList[i]; 70 } 71 } 72 return *this; 73 } 74 75 bool SeqList::empty() const 76 { 77 return lenOfList == 0; 78 } 79 80 void SeqList::clear() 81 { 82 lenOfList = 0; 83 fill(seqList, seqList + myCapacity - 1, 0); 84 } 85 86 bool SeqList::insert(const int pos, const ElementType val) 87 { 88 bool success = false; 89 // assert(lenOfList != CAPACITY); // 这里的assert分成两行写,是为了方便定位错误发生的地方 90 // assert(0 <= pos <= lenOfList); 91 if (lenOfList == myCapacity) 92 { 93 cerr << "No space for insertion!" << endl; 94 } 95 else if (pos < 0 || pos > lenOfList) 96 { 97 cerr << "The position " << pos << 98 " you want to insert is less than zero or exceeds the length of the list!" << endl; 99 throw out_of_range("throw out_of_range"); // 抛出一个越界异常 100 } 101 else 102 { 103 int tmpCount = lenOfList - pos; 104 for (int i = 0; i < tmpCount; i++) 105 { 106 seqList[lenOfList - i] = seqList[lenOfList - i - 1]; 107 } 108 seqList[pos] = val; 109 lenOfList++; 110 success = true; 111 } 112 return success; 113 } 114 115 bool SeqList::erase(const int pos) 116 { 117 bool success = false; 118 // assert(lenOfList != 0); 119 // assert(0 <= pos <= lenOfList); 120 if (lenOfList == 0) 121 { 122 cerr << "There is no elements in the list!" << endl; 123 } 124 else if (pos < 0 || pos > lenOfList) 125 { 126 cerr << "The position " << pos << 127 " you want to erase is less than zero or exceeds the length of the list!" << endl; 128 throw out_of_range("throw out_of_range"); // 抛出一个越界异常 129 } 130 else 131 { 132 int tmp = lenOfList - pos; 133 for (int i = 0; i < tmp - 1; i++) 134 { 135 seqList[pos + i] = seqList[pos + i + 1]; 136 } 137 seqList[lenOfList - 1] = 0; 138 lenOfList--; 139 success = true; 140 } 141 return success; 142 } 143 144 void SeqList::display() const 145 { 146 cout << "***Start Displaying***" << endl; 147 if (lenOfList == 0) 148 { 149 cerr << "There is no element in the the list!" << endl; 150 } 151 else 152 { 153 for (int i = 0; i < lenOfList; i++) 154 { 155 cout << i << " : " << seqList[i] << endl; 156 } 157 cout << "***End Displaying***" << endl; 158 } 159 } 160 161 bool SeqList::setSeqList(const ElementType *tmpList, const int len) 162 { 163 // assert(len <= CAPACITY); 164 bool success = false; 165 if (len <= myCapacity) 166 { 167 for (int i = 0; i < len; i++) 168 { 169 seqList[i] = *(tmpList++); 170 } 171 lenOfList = len; 172 success = true; 173 } 174 else 175 { 176 cerr << "The length of the array you set exceeds the CAPACITY." << endl; 177 throw out_of_range("throw out_of_range"); // 抛出一个越界异常 178 } 179 return success; 180 } 181 182 int SeqList::getLenOfList() const 183 { 184 return lenOfList; 185 } 186 187 ElementType SeqList::getItem(const int pos) 188 { 189 // assert(0 <= pos <= lenOfList); 190 if (pos < 0 || pos > lenOfList) 191 { 192 cerr << "The item at " << pos << " you want to get does not exist!" << endl; 193 throw out_of_range("throw out_of_range"); // 抛出一个越界异常 194 } 195 else 196 { 197 return seqList[pos]; 198 } 199 } 200 201 ElementType * SeqList::getSeqList() 202 { 203 return seqList; 204 }