单向链表实现

#include<iostream>
#include <sstream>

using namespace std;

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 outputMessge() {
        cout << message << endl;
    }

private:
    string message;
};

// 链表结点的结构定义
template<class T>
struct chainNode {
    // 数据成员
    T element;
    chainNode<T> *next;

    // 方法
    chainNode() {}

    chainNode(const T &element) { this->element = element; }

    chainNode(const T &element, chainNode<T> *next) {
        this->element = element;
        this->next = next;
    }
};

template<class T>
class chainList {
public:
    // 构造函数,复制构造函数和构析函数
    chainList(int initialCapacity = 10);

    chainList(const chainList<T> &);

    ~chainList();

    // 抽象数据类型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;

protected:
    void checkIndex(int theIndex) const; // 如果索引无效抛出异常
    chainNode<T> *firstNode; // 指向链表第一个结点的指针
    int listSize;
};

template<class T>
void chainList<T>::checkIndex(int theIndex) const {
    if (theIndex < 0 || theIndex >= size()) {
        stringstream s;
        s << "theIndex " << theIndex << " is illegal";
        illegalParameterValue(s.str());
    }
}

// 构造函数和复制构造函数
template<class T>
chainList<T>::chainList(int initialCapacity) {
    // 构造函数
    if (initialCapacity < 1) {
        ostringstream s;
        s << "Initial capacity = " << initialCapacity << " Muse be > 0 ";
        throw illegalParameterValue(s.str());
    }
    firstNode = nullptr;
    listSize = 0;
}

template<class T>
chainList<T>::chainList(const chainList<T> &theList) {
    // 复制构造函数
    listSize = theList.listSize;
    if (listSize == 0) {
        // 链表theList为空
        firstNode = nullptr;
        return;
    }
    // 链表theList为非空
    chainNode<T> *sourceNode = theList.firstNode; // 复制链表theList的节点
    firstNode = new chainNode<T>(sourceNode->element); // 复制链表theList的首元素
    sourceNode = sourceNode->next;
    chainNode<T> *targetNode = firstNode; // 当前链表*this的最后一个结点
    while (sourceNode != nullptr) {
        // 复制剩余元素
        targetNode->next = new chainNode<T>(sourceNode->element);
        targetNode = targetNode->next;
        sourceNode = sourceNode->next;
    }
    targetNode->next = nullptr; // 链表结束
}

// 构析函数
template<class T>
chainList<T>::~chainList() {
    // 链表构析函数,删除链表的所有节点
    while (firstNode != nullptr) {
        // 删除首结点
        chainNode<T> *nextNode = firstNode->next;
        delete firstNode;
        firstNode = nextNode;
    }
}

// get方法
template<class T>
T &chainList<T>::get(int theIndex) const {
    // 返回索引为theIndex的㢝
    // 若该元素不存在,则抛出异常
    checkIndex(theIndex);
    // 移向所需要的结点
    chainNode<T> *currentNode = firstNode;
    for (int i = 0; i < theIndex; ++i)
        currentNode = currentNode->next;
    return currentNode->element;
}

// 返回元素theElement首次出现时的索引
template<class T>
int chainList<T>::indexOf(const T &theElement) const {
    // 返回元素theElement首次出现时的索引
    // 若该元素不存在,则返回-1
    // 搜寻链表寻找元素theElement
    chainNode<T> *currentNode = firstNode;
    int index = 0;
    while (currentNode != nullptr && currentNode->element != theElement) {
        // 移向下一个结点
        currentNode = currentNode->next;
        ++index;
    }
    // 确定是否找到所需的元素
    if (currentNode == nullptr)
        return -1;
    else
        return index;
}

// 删除索引为theIndex的元素
template<class T>
void chainList<T>::erase(int theIndex) {
    // 删除索引为theIndex元素
    // 若该元素不存在,则抛出异常
    checkIndex(theIndex);
    // 索引有效
    chainNode<T> *deleteNode;
    if (theIndex == 0) {
        // 删除链表的头节点
        deleteNode = firstNode;
        firstNode = firstNode->next;
    } else {
        // 用指针p指向要删除节点的前驱结点
        chainNode<T> *p = firstNode;
        for (int i = 0; i < theIndex - 1; ++i)
            p = p->next;
        deleteNode = p->next;
        p->next = p->next->next;
    }
    --listSize;
    delete deleteNode;
}

// 插入theElement并使得其索引为theIndex
template<class T>
void chainList<T>::insert(int theIndex, const T &theElement) {
    // 在索引为theIndex的位置上
    // 若该位置非法,则抛出异常
    if (theIndex < 0 || theIndex > listSize) {
        // 无效索引
        ostringstream s;
        s << "index = " << theIndex << " size = " << listSize;
        throw illegalParameterValue(s.str());
    }
    if (theIndex == 0)
        // 在链表头插入
        firstNode = new chainNode<T>(theElement, firstNode);
    else {
        // 寻找新元素的前驱结点
        chainNode<T> *p = firstNode;
        for (int i = 0; i < theIndex - 1; ++i)
            p = p->next;
        // 在p之后插入
        p->next = new chainNode<T>(theElement, p->next);
    }
    ++listSize;
}

template<class T>
void chainList<T>::output(ostream &out) const {
    // 把链表放入输出流
    for (chainNode<T> *currentNode = firstNode; currentNode != nullptr; currentNode = currentNode->next)
        out << currentNode->element << " ";
}

// 重载
template<class T>
ostream &operator<<(ostream &out, const chainList<T> &x) {
    x.output(out);
    return out;
}

int main() {
    auto *array1 = new chainList<int>(20);
    array1->insert(0, 1);
    array1->insert(1, 2);
    array1->insert(2, 3);
    cout << *array1 << endl;
    array1->insert(4, 4);
    return 0;
}
terminate called after throwing an instance of 'illegalParameterValue'
1 2 3 
index = 4 size = 3
posted @ 2022-05-28 22:35  里列昂遗失的记事本  阅读(35)  评论(0编辑  收藏  举报