线性表的数组表示
参考资料《数据结构,算法与应用》c++版。
1.简介
线性表有多种表示方法,其中一种是利用c++中的内置数组来实现的,此种方法也称为静态存储。如何确定线性表的第0个元素和第n-1个(最后一个)元素在数组的位置呢?我们需要一种映射,或者说一个公式来快速地定位元素在数组中的位置。
一种常见的方法就是:location(i) = i ,线性表的起始位置和数组的起始位置正好重合。正因为有这种映射,可以让我们很快的得到对应索引的元素。
为了简化起见,这里不包含错误提示,假设用户能够正确的使用以及索引元素,不会出现越界这类操作。
2. 线性表的数组表示
以下为线性表的数组实现类:
先看私有成员变量,一个代表用来储存线性表的数组,剩下两个分别表示数组和线性表的大小。
再看成员函数,构造函数(生成一个初始容量为10的数组),复制构造函数以及析构函数。
其余的便是标准的ADT函数。
// Definition of arrayList
template <typename T>
class arrayList {
public:
arrayList(int initialCapacity = 10); // ctor
arrayList(const arrayList<T>&); // copy ctor
~arrayList() { delete[] element; } // dtor
bool empty() const { return listSize == 0; }
int size() const { return listSize; }
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
int capacity() const { return arrayLength; }
private:
T* element; // array to store list
int arrayLength; // capacity of array
int listSize; // number of element in list
};
3. 线性表的数组实现
// ctor
template <typename T>
arrayList<T>::arrayList(int initialCapacity = 10)
: element(new T[initialCapacity]),
arrayLength(initialCapacity),
listSize(0) {}
// copy ctor
template <typename T>
arrayList<T>::arrayList(const arrayList<T>& theList) {
arrayLength = theList.arrayLength;
listSize = theList.listSize;
element = new T[theList.arrayLength];
std::copy(theList.element, theList.element + theList.listSize, element);
}
template <typename T>
T& arrayList<T>::get(int theIndex) const {
return element[theIndex];
}
template <typename T>
int arrayList<T>::indexOf(const T& theElement) const {
// return the index of first occurence of theElement
// return -1 if theElement is not in list
for (int i = 0; i < listSize; i++) {
if (theElement == element[i])
return i;
else
return -1;
}
}
template <typename T>
void arrayList<T>::erase(int theIndex) {
// left shift one element: shift element[index+1,listSize) to
// element[index,listSize-1), and delete last element element[listSize-1]
std::copy(element + theIndex + 1, element + listSize, element + theIndex);
element[--listSize].~T();
}
template <typename T>
void arrayList<T>::insert(int theIndex, const T& theElement) {
// if the arrayList is full, double the arrayLength
if (listSize == arrayLength) {
changeLength1D(element, arrayLength, 2 * arrayLength);
arrayLength *= 2;
}
// right shift: element[index, listSize) -> element[index+1, listSize + 1)
// backward copy
std::copy_backward(element + theIndex, element + listSize,
element + listSize + 1);
element[theIndex] = theElement;
listSize++;
}
template <typename T>
void changeLength1D(T*& array, int oldLength, int newLength) {
T* new_array = new T[newLength];
int number = min(oldLength, newLength);
std::copy(array, array + number, new_array); // stl copy
delete[] array;
array = new_array; // make old array become new array
}
4.注意事项
这里用了一些STL的算法,比如copy,copy_backward。
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = *first;
++result; ++first;
}
return result;
}
template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 copy_backward ( BidirectionalIterator1 first,
BidirectionalIterator1 last,
BidirectionalIterator2 result )
{
while (last!=first) *(--result) = *(--last);
return result;
}
参数first和last没什么好说的,代表着你想复制的元素的首尾地址(迭代器)。对于result,copy中代表的是目标的首元素地址,而copy_backward中代表的是目标的最后一位还要加一的地址(末尾哨兵)。
因为数组为静态储存,对于静态操作,比如查找,只需常数时间O(1)。而对于动态操作,比如插入,删除,则需要O(n)的时间。