1. 程式人生 > 其它 >動態陣列(C++)

動態陣列(C++)

#include<iostream>
#include <sstream>
#include<iterator>
#include<algorithm>

using namespace std;

// 重寫copy程式碼
template<class iterator>
void copy(iterator start, iterator end, iterator to) {
    // 從start複製到[to, to+end-start)
    while (start != end)
        *(to++) = *(start++);
}

template<class T>
class linearList {
public:
    virtual ~linearList() = default;;

    virtual bool empty() const = 0; /* 返回true,當且僅當線性表為空 */
    virtual int size() const = 0; /* 返回線性表的元素個數 */
    virtual T &get(int theIndex) const = 0; /* 返回索引為theIndex的元素 */
    virtual int indexOf(const T &theElement) const = 0; /* 返回元素theElement第一次出現時的索引 */
    virtual void erase(int theIndex) = 0; /* 刪除索引為theIndex的元素 */
    virtual void insert(int theIndex, const T &theElement) = 0;/* 把theElement插入線性表中索引為theIndex的位置上 */
    virtual void output(ostream &out) const = 0;/*把線性表插入輸出流*/
};

class illegalParameterValue {
public:
    illegalParameterValue() : message("Illegal parameter value") {}

    explicit illegalParameterValue(char *theMessage) {
        message = theMessage;
    }

    explicit illegalParameterValue(const string &theMessage) {
        message = theMessage;
        cout << message << endl;
    }

    void outputMessage() { cout << message << endl; }

private:
    string message;
};

/* 改變一個一位陣列的長度*/
template<class T>
void changeLength1D(T *&a, int oldLength, int newLength) {
    if (newLength < 0)  /* 如果新表長小於0 */
        throw illegalParameterValue("new length muse be >= 0"); /* 丟擲異常*/
    T *temp = new T[newLength]; /* 申請新的陣列空間*/
    int number = min(oldLength, newLength); /*過的原來陣列長度和現在陣列長度中較小者*/
    copy(a, a + number, temp); /* 將原陣列中的資料放到新的陣列中*/
    delete[] a; /* 刪除原來陣列的空間*/
    a = temp; /*將新陣列空間的地址給原來的陣列名*/
}

/* 類arrayList定義
 * 定義抽象類linearList的派生類arrayList
 * 來實現抽象資料型別linearList
*/
template<class T>
class arrayList : public linearList<T> {
public:
    /* 建構函式,複製建構函式和構析函式 */
    arrayList(int initialCapacity = 10);

    arrayList(const arrayList<T> &);

    ~arrayList() { delete[]element; }

    /* ADT方法 */
    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;

    T *element; /* 儲存線性表元素的一維陣列 */
    int arrayLength; /* 一維陣列的容量 */
    int listSize; /* 線性表的元素個數 */
};

template<class T>
void arrayList<T>::checkIndex(int theIndex) const {
    if (theIndex < 0 || theIndex >= listSize) {
        ostringstream s;
        s << "index = " << theIndex << " size = " << listSize;
        throw illegalParameterValue(s.str());
    }
}

template<class T>
T &arrayList<T>::get(int theIndex) const {
    // 返回索引為theIndex的元素
    // 若此元素不存在,則丟擲異常
    checkIndex(theIndex);
    return element[theIndex];
}

template<class T>
int arrayList<T>::indexOf(const T &theElement) const {
    // 返回元素theElement第一次出現時的索引
    // 若該元素不存在,則返回-1
    // 查詢元素theElement
    int theIndex = (int) (find(element, element + listSize, theElement) - element);
    // 確定theElement是否找到
    if (theIndex == listSize)
        // 沒有找到
        return -1;
    else
        return theIndex;
}

template<class T>
void arrayList<T>::erase(int theIndex) {
    // 刪除其索引為theIndex的元素
    // 如果該元素不存在,則丟擲illegal
    checkIndex(theIndex);
    // 有效索引,移動其索引大於theIndex的元素
    copy(element + theIndex + 1, element + listSize, element + theIndex);
    element[--listSize].~T(); // 呼叫構析函式
}

// arrayList的建構函式
template<class T>
arrayList<T>::arrayList(int initialCapacity) {
    // 建構函式
    if (initialCapacity < 1) {
        ostringstream s;
        s << "Initial capacity = " << initialCapacity << " Must be > 0";
        throw illegalParameterValue(s.str());
    }
    arrayLength = initialCapacity;
    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>
void arrayList<T>::insert(int theIndex, const T &theElement) {
    // 在索引theIndex處插入元素theElement
    if (theIndex < 0 || theIndex > listSize) {
        // 無效索引
        ostringstream s;
        s << "index = " << theIndex << " size = " << listSize;
        throw illegalParameterValue(s.str());
    }
    // 有效索引,確認陣列是否已滿
    if (listSize == arrayLength) {
        // 陣列空間已滿,陣列長度倍增
        changeLength1D(element, arrayLength, arrayLength * 2);
        arrayLength *= 2;
    }
    // 把元素向右移動一個位置
    copy_backward(element + theIndex, element + listSize, element + listSize + 1);
    element[theIndex] = theElement;
    ++listSize;
}

// 把一個線性表插入輸出流
template<class T>
void arrayList<T>::output(ostream &out) const {
    copy(element, element + listSize, ostream_iterator<T>(cout, " "));
}

// 過載<<
template<class T>
ostream &operator<<(ostream &out, const arrayList<T> &x) {
    x.output(out);
    return out;
}

int main() {
    auto *array1 = new arrayList<int>(100);
    arrayList<double> y(100);
    cout << *array1 << endl;
    cout << y << endl;
    return 0;

}