C++實現陣列構造的線性表
阿新 • • 發佈:2019-02-04
#include<iostream> #include<algorithm>//copy,copy_backward函式 #include<sstream> //ostringstream #include<string> //字串 #include<exception>//異常處理 #include<iterator> //ostream_iterator<T>輸出流 using namespace::std; //改變二維陣列的長度,每一維都可以變化 /*template<typename T> void changeLength2D(T ** &a, unsigned oldRow,unsigned oldCol,unsigned newRow, unsigned newCol) { T **b = new T*[newRow]; for (unsigned i = 0; i != newRow; ++i) b[i] = new T[newCol]; unsigned row, col; row = min(oldRow, newRow); col = min(oldCol, newCol); for (unsigned i = 0; i != row; ++i) { copy(a[i], a[i]+col,b[i]); } for (unsigned i = 0; i != oldRow; ++i) { delete[] a[i]; } delete[] a; a = b; }*/ //異常類 /*class illegalParameterValue { public: illegalParameterValue(): message("Illegal parameter value") { } illegalParameterValue(char* theMessage) { message = theMessage; } void outputMessage() { cout << message << endl; } private: string message; };*///和上面的類做區別s.str()是代表的具體類容,因此不可用上面的(直接賦語句卻是可以的) class illegalParameterValue { public: illegalParameterValue(string theMessage = "Illegal parameter value") { message = theMessage; } void outputMessage() { cout << message << endl; } private: string message; }; class illegalIndex { public: illegalIndex(string theMessage = "Illegal index") //初始化 { message = theMessage; } void outputMessage() { cout << message << endl; } private: string message; }; //在類arayList中增加一個建構函式,允許你指定一個值,當陣列空間滿時改變該陣列長度 template<typename T> class arrayList//:public linearList<T> { public: //建構函式,新加的建構函式,解構函式 arrayList(int initialCapacity = 10); arrayList(unsigned theLengthChange = 0, int initialCapacity = 10); ~arrayList() { delete[] element; } //ADT方法 void insert(int theIndex, const T& theElement); void changeLength1D(T* &a, int oldLength, int newLength); void output(ostream& out) const; void trimToSize(); T operator[](const int i); void push_back(const T& thelement); void pop_back(); void clear(); int lastIndexof(const T& theElement); void reverse(); void circularShift(int i); private: T* element; int arrayLength; int listsize; unsigned LengthChange; }; //建構函式以及其他函式的定義 template<typename T> arrayList<T>::arrayList(int initialCapacity) { if (initialCapacity < 1) { ostringstream s; s << "Initial capacity=" << initialCapacity << "Must be >0"; throw illegalParameterValue(s.str());//s.str(()返回s中儲存的string 物件 } arrayLength = initialCapacity; element = new T[arrayLength]; listsize = 0; LengthChange = 0; //一定要保證類的private的值都有值,即使為0 } //多增加了要改變的長度 template<typename T> arrayList<T>::arrayList(unsigned theLengthChange,int initialCapacity) { if (initialCapacity < 1) { ostringstream s; s << "Initial capacity=" << initialCapacity << "Must be >0"; throw illegalParameterValue(s.str());//s.str(()返回s中儲存的string 物件 } arrayLength = initialCapacity; element = new T[arrayLength]; listsize = 0; LengthChange = theLengthChange; } //插入函式 template<typename T> void arrayList<T>::insert(int theIndex, const T& theElement) { if (theIndex<0 || theIndex>listsize) { ostringstream s; s <<"index= " << theIndex << "size= " << listsize; throw illegalIndex(s.str()); } if (LengthChange) { changeLength1D(element, arrayLength, LengthChange); arrayLength = LengthChange; } else { changeLength1D(element, arrayLength, 2*arrayLength); arrayLength *=2; } //把theIndex之後的元素向後移動一位 copy_backward(element + theIndex, element + listsize, element + listsize + 1); element[theIndex] = theElement; listsize++; } //改變一維陣列長度的函式 template<typename T> void arrayList<T>::changeLength1D(T* &a, int oldLength, int newLength) { if (newLength < 0) throw illegalParameterValue("new lenght must be>=0"); T*temp = new T[newLength]; int number = min(oldLength, newLength); copy(a, a + number, temp); delete[] a; a = temp; } //輸出函式 template<typename T> void arrayList<T>::output(ostream& cout) const { copy(element, element + listsize, ostream_iterator<T>(cout, " ")); } //使陣列長度大小為max(size,1) template<typename T> void arrayList<T>::trimToSize() { int size = max(listsize, 1); T *b = new T[size]; copy(element, element + size, b); //複雜度為O(listSize); delete[] element; element = b; } //過載操作符[] template<typename T> T arrayList<T>::operator[](const int i) { if (i<0 || i>listsize) { ostringstream s; s << "i=" << i; throw illegalIndex(s.str()); } return element[i]; } //編寫方法push_back,把元素插入到線性表的右端 template<typename T> void arrayList<T>::push_back(const T& thelement) { element[listsize]= thelement; //複雜度O(1) listsize++; } //編寫方法pop_back,把右端的元素刪除 template<typename T> void arrayList<T>::pop_back() { element[--listsize].~T();//刪除最後一個元素複雜度O(1) } //編寫方法,將線性表清空 template<typename T> void arrayList<T>::clear() { for(int i=listsize-1;i>=0;i--) //複雜度O(listsize) element[--listsize].~T(); } //編寫尋找函式,藉助於函式find(可以找到元素第一次出現的迭代器),要找到元素最後出現的索引 template<typename T> int arrayList<T>::lastIndexof(const T& theElement) { int i = listsize,j=0,theIndex=listsize; //這樣初始化(不選擇0)是為了確保要找的元素就是第一個元素而不出錯 do //而且也保證瞭如果沒有元素匹配時有判斷條件,變成while的,i=0就會有兩種情況,要麼在首位,要麼無要找的元素 { i = theIndex; theIndex = (int)(find(element + j, element + listsize, theElement) - element);//方法的時間複雜度為O(n)(最壞) j=theIndex+1; } while (theIndex < listsize); if (i==listsize) return -1; else return i; } //編寫原地顛倒函式,不用STL中的reverse template<typename T> void arrayList<T>::reverse() { T a; for (int i = 0; i < listsize/2; i++) //交換了listsize/2,複雜度O(listsize/2) { a = element[i]; element[i] = element[listsize - i - 1]; element[listsize-i-1] = a; } } //編寫迴圈移動函式(順時針旋轉) template<typename T> void arrayList<T>::circularShift(int i) { T* b = new T[listsize]; while(i) { copy(element, element + listsize, b); for (int j = 0; j < listsize-1; j++) { element[j] = b[j+1]; } element[listsize - 1] = b[0]; i--; } delete[] b; } int main() { /*//對二維陣列的改變進行測試 int row = 2, col = 3; int temp[2][3]= { 1, 2, 3, 4, 5, 6 }; //給陣列a分配空間 int **a = new int*[row]; for (size_t i = 0; i != row; ++i) { a[i] = new int[col]; } //用temp給陣列初始化 for (size_t i = 0; i != row; ++i) for (size_t j = 0; j != col; ++j) a[i][j] = temp[i][j]; changeLength2D(a, 2, 3, 3, 4); //給未複製到的元素賦值,只有在新陣列長度大於原陣列長度時才用 for (size_t i = 0; i != 3; ++i) for (size_t j = 3; j != 4; ++j) a[i][j] = 0; for (size_t i = 2; i != 3; ++i) for (size_t j = 0; j != 4; ++j) a[i][j] = 0; //輸出新的陣列的值 for (size_t i = 0; i != 3; ++i) { for (size_t j = 0; j != 4; ++j) { cout << a[i][j] << ' '; } cout << '\n'; }*/ //對插入函式進行測試 //arrayList<int>y(3); /*arrayList<int>y(6,3); //第一位表示要更改的陣列長度,第二位表示原長度 y.insert(0, 2); y.insert(1, 6); y.insert(0, 1); y.insert(2, 4); y.insert(3, 5); y.insert(2, 3); y.output(cout);*/ //對改變陣列長度進行測試 /*arrayList<int>y(10); y.insert(0, 2); y.insert(1, 6); y.trimToSize(); //異常丟擲測試 try { y.insert(3, 0); } catch (illegalIndex e) { cout << "Illegal index exception" << endl; cout << "Insert index must be between 0 and list size" << endl; e.outputMessage(); }*/ //測試過載操作符[] /*arrayList<int>y(3); y.insert(0, 2); y.insert(1, 6); int s=y[1]; //測試異常丟擲 try { y[6]; } catch (illegalIndex e) { cout << "Illegal index exception" << endl; e.outputMessage(); } cout <<s<<endl;*/ //測試push_back /*arrayList<int>y(3); y.push_back(2); y.push_back(3); //測試pop_back y.pop_back(); //測試清空 y.clear(); y.output(cout);*/ //對lastIndexOf函式進行測試5 arrayList<int>y(10); y.push_back(0); y.push_back(1); y.push_back(2); y.push_back(3); y.push_back(4); /*int i = y.lastIndexof(4); cout << i << endl;*/ //原地顛倒測試 //y.reverse(); //迴圈移動測試 y.circularShift(2); y.output(cout); return 0; }