线性表应该实施下列操做:ios
- 建立一个线性表
- 撤销一个线性表
- 肯定线性表是否为空
- 肯定线性表的长度
- 按一个给定的索引查找一个元素
- 按一个给定的元素查找其索引
- 按一个给定的索引删除一个元素
- 按一个给定的索引插入一个元素
- 从左至右顺序输出线性表元素
template<class T> class linearList { public: virtual ~linearList(){}; //判断线性表是否为空 virtual bool empty() const = 0; //计算线性表元素个数 virtual int size() const = 0; //返回索引为theIndex的元素 virtual T& get(int theIndex) const = 0; //返回元素theElement第一次出现时的索引 virtual int indexOf(const T& theElement) const = 0; //删除索引为theIndex的元素 virtual void erase(int theIndex) = 0; //把元素theElement插入到索引为theIndex的位置 virtual void insert(const T& theElement,int theIndex) = 0; //把线性表插入输出流out virtual void output(ostream out) const = 0; }
要建立一个数组类。以实现抽象数据类型linearList,必须首先选择数组element的类型和数组长度。
解决第一个问题能够经过使用模板类。
解决第二个问题可使用动态数组。首先估计一个初始数组长度,而后在数组空间不足的状况下,动态的增长数组长度。
当数组满而须要增大数组长度时,数组长度经常是要加倍的。这个过程称为数组倍增。(array doubling)。数组倍增的时间,从渐进意义上考量,不会大于元素插入的总时间。windows
//变长数组实现 template<class T> void changeLength1D(T*& a,int oldLength,int newLength) { if(newLength<0) cout<<"the length should > 0"<<endl; T* temp = new T[newLength]; int number = min(oldLength,newLength);//须要复制的元素个数 copy(a,a+number,temp); delete [] a;//释放老数组的内存空间 a = temp; }
.定义一个C++抽象类linearList的派生类arrayList。arrayList是一个具体的类,实现了抽象类linearList的全部方法,而且还有arrayList中没有的方法,好比capacity()和checkindex()。数组
//具体类arrayList的实现 template<class T> class arrayList:public linearList<T>//尖括号中的类型规定了linearList只能 //保存T类型的数据 { public: arrayList(int initialCapacity = 10);//构造函数 arrayList(const arrayList<T>&);//复制构造函数 ~arrayList(){delete [] element;}//析构函数 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); void output(ostream out) const; //其余方法 int capacity() const {return arrayLength;} protected: void checkIndex(int theIndex) const; //若索引theIndex无效,则抛出异常 T* element;//存储线性表元素的一维数组 int arrayLength;//一维数组的容量 int listSize;//线性表的元素个数 }
下面是具体类中函数的具体实现:数据结构
//arrayList的构造函数 template<class T> arrayList<T>::arrayList(int initialCapacity) { if(initialCapacity < 1) cout<<"数组为空"<<endl; arrayLength = initialCapacity; element = new T[arrayLength]; listSize = 0; } //复制构造函数 template<class T> arrayList::arrayList(const arrayList<T>& theList) { arrayLength = theList.arrayLength; element = new T[arrayLength]; copy(theList.element,theList.element+listSize,element); } //erase()函数的实现 template<class T> void arrayList::erase(int theIndex) { checkIndex(theIndex);//先判断元素是否存在 //移动索引theIndex以后的全部元素 copy(element+theIndex+1,element+listSize,element+theIndex); element[--listSize].~T();//调用析构函数 } //在索引为theIndex的位置插入元素theElement template<class T> void arrayList::insert(int theIndex,T& theElement) { if(theIndex < 0 || theIndex > listSize) cout<<"元素索引不在合理范围内!"<<endl; //索引有效,肯定数组是否已满 if(listSize ==arrayLength) changeLength1D(element,arrayLength,2*arrayLength); arrayLength *= 2; copy_backward(element+theIndex,element+theList,element+listSize+1); element(theIndex) = theElement; listSize++; } //checkIndex()方法实现 template<class T> void arrayList<T>::checkIndex(int theIndex) const { if(theIndex < 0 || theIndex >= listSize) cout<<"提供的索引不在合理范围内!"<<endl; } //get()方法实现 template<class T> T& arrayList<T>::get(int theIndex) const { checkIndex(theIndex); return element[theIndex]; } //indexOf()函数实现 template<class T> int arrayList<T>::indexOf(const T& theElement) const { //查找元素theElement int theIndex = (int)(find(element,element+listSize,theElement)-element); //肯定元素theElement是否找到 if(theIndex == listSize) return -1; else return theIndex; } //erase()函数的实现 template<class T> void arrayList::erase(int indexOf) { checkIndex(theIndex); copy(element+theIndex+1,element+listSize,element+theIndex); element[--listSize].~T(); } //insert()函数的实现 void arrayLength::insert(int theIndex,const T& theElement) { if(theIndex < 0 || theIndex >= listSize) cout<<"索引范围不合法"<<endl; if(listSize == arrayLength) { changeLength1D(element,arrayLength,2*arrayLength); arrayLength*=2; } copy_backward(element+theIndex,element+listSize,element+listSize+1); element[theIndex] = theElement; listSize++; }
如下是能够在Qt5.1中成功运行的完整代码(windows平台):
在Mac平台报错:linker command line with exit code 1(use -v to see invocation)
Mac中的这种报错,网上有不少教程,我试了几种,都没有用。by the way,我在Mac上的使用clang编译。先放着吧,这问题之后再解决:函数
#include<iostream> #include<stdlib.h> #include<algorithm> using namespace std; //改变一个一维数组的长度 template<class T> void changeLength1D(T*& a,int oldLength,int newLength) { if(newLength >= 0) { T* temp = new T[newLength]; int number = min(oldLength,newLength);//须要复制的元素个数 copy(a,a+number,temp); delete [] a;//释放老数组的内存空间 a = temp; } } int min(int a,int b) { if(a >= b) return b; else return a; } /* * 一个线性表的抽象类 */ template<class T> class linearList { public: virtual ~linearList(){}; virtual bool empty() const = 0; virtual int size() const = 0; virtual T& get(int theIndex) const = 0; virtual int indexOf(const T& theElement) const = 0; virtual void erase(int theIndex) = 0; virtual void insert(int theIndex,const T& theElement) = 0; virtual void output(ostream& out) const = 0; }; /* * 线性表具体类的定义 * 类名:arrayList */ template<class T> class arrayList : public linearList<T> { public: //构造函数 arrayList(int initialCapacity = 10); //复制构造函数 arrayList(const arrayList<T>&); //析构函数 ~arrayList(); //具体函数声明 bool empty() const; int size() const; T& get(int theIndex) const; int indexOf(const T &theElement) const; void erase(int theIndex); void insert(int theIndex,const T& theElement); void output(ostream& out) const; //其余方法 int capacity() const; protected: bool checkIndex(int theIndex) const; T* element; int listSize; int arrayLength; }; /* * 具体类中的函数具体实现 */ //构造函数 template<class T> arrayList<T>::arrayList(int initiaCapacity) { if(checkIndex(initiaCapacity)) { arrayLength = initiaCapacity; element = new T[arrayLength]; listSize = 0; } } //复制构造函数 template<class T> arrayList<T>::arrayList(const arrayList<T>& theList) { arrayLength = theList.arrayLength; listSize = theList.listSize; element = new T[arrayLength]; copy(theList.element,theList.element+listSize,element); } //析构函数 template<class T> arrayList<T>::~arrayList() { delete [] element; } //bool empty() template<class T> bool arrayList<T>::empty()const { return listSize == 0; } //int size() template<class T> int arrayList<T>::size() const { return listSize; } //T& get() template<class T> T& arrayList<T>::get(int theIndex) const { if(checkIndex(theIndex)) { return element[theIndex]; } } //int indexOf() template<class T> int arrayList<T>::indexOf(const T &theElement) const { int theIndex = (int)(find(element,element+listSize,theElement)-element); if(theIndex == listSize) return -1; else return theIndex; } //void erase() template<class T> void arrayList<T>::erase(int theIndex) { if(checkIndex(theIndex)) { copy(element+theIndex+1,element+listSize,element+theIndex); element[--listSize].~T();//调用析构函数 } } //void insert() template<class T> void arrayList<T>::insert(int theIndex, const T &theElement) { if(checkIndex(theIndex)) { if(listSize == arrayLength) { //数组空间已满,数组长度倍增 changeLength1D(element,arrayLength,2*arrayLength); arrayLength *= 2; } //把数组向右移动一个位置 copy_backward(element+theIndex,element+listSize,element+listSize+1); element[theIndex] = theElement; listSize++; } } //核对元素索引是否合法 template<class T> bool arrayList<T>::checkIndex(int theIndex) const { if(theIndex<0 || theIndex >= listSize) return false; else return true; } //output(ostream& out) template<class T> void arrayList<T>::output(ostream &out) const { for(int i = 0;i<listSize;i++) out<<element[i]<<" "; } //重载<< template<class T> ostream& operator<<(ostream& out,const arrayList<T>& x) { x.output(out); return out; } //int capacity() const; template<class T> int arrayList<T>::capacity()const { return arrayLength; } int main(void) { // test constructor linearList<double> *x = new arrayList<double>(20); arrayList<int> y(2), z; // test capacity cout << "Capacity of x, y and z = " << ((arrayList<double>*) x)->capacity() << ", " << y.capacity() << ", " << z.capacity() << endl; // test size cout << "Initial size of x, y, and z = " << x->size() << ", " << y.size() << ", " << z.size() << endl; // test empty if (x->empty()) cout << "x is empty" << endl; else cout << "x is not empty" << endl; if (y.empty()) cout << "y is empty" << endl; else cout << "y is not empty" << endl; // test insert y.insert(0, 2); y.insert(1, 6); y.insert(0, 1); y.insert(2, 4); y.insert(3, 5); y.insert(2, 3); cout << "Inserted 6 integers, list y should be 1 2 3 4 5 6" << endl; cout << "Size of y = " << y.size() << endl; cout << "Capacity of y = " << y.capacity() << endl; if (y.empty()) cout << "y is empty" << endl; else cout << "y is not empty" << endl; y.output(cout); cout << endl << "Testing overloaded <<" << endl; cout << y << endl; // test indexOf int index = y.indexOf(4); if (index < 0) cout << "4 not found" << endl; else cout << "The index of 4 is " << index << endl; index = y.indexOf(7); if (index < 0) cout << "7 not found" << endl; else cout << "The index of 7 is " << index << endl; // test get cout << "Element with index 0 is " << y.get(0) << endl; cout << "Element with index 3 is " << y.get(3) << endl; // test erase y.erase(1); cout << "Element 1 erased" << endl; cout << "The list is " << y << endl; y.erase(2); cout << "Element 2 erased" << endl; cout << "The list is " << y << endl; cout << "Size of y = " << y.size() << endl; cout << "Capacity of y = " << y.capacity() << endl; if (y.empty()) cout << "y is empty" << endl; else cout << "y is not empty" << endl; // test copy constructor arrayList<int> w(y); y.erase(0); y.erase(0); cout << "w should be old y, new y has first 2 elements removed" << endl; cout << "w is " << w << endl; cout << "y is " << y << endl; // a few more inserts, just for fun y.insert(0,4); y.insert(0,5); y.insert(0,6); y.insert(0,7); cout << "y is " << y << endl; cout<<"Hello World!"<<endl; return 0; }