線性表應該實施下列操做: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; }