• C++泛化双向链表


    泛型双向链表

    双向链表(doublyLinkedList.h)

    /*************************************************************************
    > File Name       : doublyLinkedList.h
    > Author          : Harold
    > Mail            : 2106562095@qq.com
    > Github          : www.github.com/Haroldcc
    > Created Time    : 2020年02月28日  10时23分06秒
    ************************************************************************/
    /***** 双向链表 *****/
    
    #ifndef DOUBLYLINKEDLIST_H
    #define DOUBLYLINKEDLIST_H
    
    #include "linearList.h"   // ADT
    #include "myExceptions.h" // 异常类
    #include <sstream>        // for ostringstream
    
    /*** 链表节点类 ***/
    template <typename T>
    class Node
    {
    public:
        T element;
        Node<T> *prev;
        Node<T> *next;
    
        Node(){};
        Node(const T &element) { this->element = element; }
        Node(const T &element, Node<T> *prev, Node<T> *next)
        {
            this->element = element;
            this->prev = prev;
            this->next = next;
        }
    };
    
    /*** 双向链表类 ***/
    template <typename T>
    class doublyLinkedList : public linearList<T>
    {
    private:
        void checkIndex(int index) const; // 索引异常检测
    
        Node<T> *firstNode; // 链表头节点指针
        Node<T> *lastNode;  // 链表尾节点指针
        int listSize;       // 链表的元素个数
    
    public:
        /* 构造函数 */
        doublyLinkedList(int initialCapacity = 10);
        ~doublyLinkedList();
    
        /* ADT */
        bool isEmpty() const { return this->listSize == 0; }
        int size() const { return this->listSize; }
        T &getElement(int index) const;
        void setElement(int index, const T &element);
        int indexOf(const T &element) const;
        void removeByIndex(int index);
        void removeByElement(const T &element);
        void add(const T &element);
        void add(int index, const T &element);
        void clear();
        void output(std::ostream &out) const;
    };
    
    // 默认构造
    template <typename T>
    doublyLinkedList<T>::doublyLinkedList(int initialCapacity)
    {
        if (initialCapacity < 1)
        {
            std::ostringstream s;
            s << "初始化容量 = " << initialCapacity << "必须 > 0";
            throw illegalParameterValue(s.str());
        }
        this->firstNode = nullptr;
        this->lastNode = nullptr;
        this->listSize = 0;
    }
    
    // 析构函数
    template <typename T>
    doublyLinkedList<T>::~doublyLinkedList()
    {
    }
    
    template <typename T>
    void doublyLinkedList<T>::checkIndex(int index) const
    {
        if (index < 0 || index >= this->listSize)
        {
            std::ostringstream s;
            s << "index = " << index << "size = " << this->listSize;
            throw illegalIndex(s.str());
        }
    }
    
    // 根据索引获取对应的节点,如未找到,抛异常
    template <typename T>
    T &doublyLinkedList<T>::getElement(int index) const
    {
        checkIndex(index);
    
        Node<T> *currentNode = this->firstNode;
        for (int i = 0; i < index; i++)
            currentNode = currentNode->next;
    
        return currentNode->element;
    }
    
    // 根据索引设置元素值
    template <typename T>
    void doublyLinkedList<T>::setElement(int index, const T &element)
    {
        checkIndex(index);
    
        Node<T> *currentNode = this->firstNode;
        for (int i = 0; i < index; i++)
            currentNode = currentNode->next;
    
        currentNode->element = element;
    }
    
    // 返回给定元素的索引值,若未找到返回 -1
    template <typename T>
    int doublyLinkedList<T>::indexOf(const T &element) const
    {
        Node<T> *currentNode = this->firstNode;
        int index = 0;
        while (currentNode != nullptr && currentNode->element != element)
        {
            currentNode = currentNode->next;
            index++;
        }
    
        if (currentNode == nullptr)
        {
            return -1;
        }
        else
        {
            return index;
        }
    }
    
    // 删除指定索引处的元素值,未找到元素抛异常
    template <typename T>
    void doublyLinkedList<T>::removeByIndex(int index)
    {
        checkIndex(index);
    
        Node<T> *deleteNode;
        if (index == 0)
        { // 删除链表中的第一个元素
            deleteNode = this->firstNode;
            this->firstNode = this->firstNode->next;
        }
        else
        {
            Node<T> *p = this->firstNode;
            for (int i = 0; i < index - 1; i++)
                p = p->next;
    
            deleteNode = p->next;
            p->next = p->next->next;
        }
        this->listSize--;
        delete deleteNode;
    }
    
    template <typename T>
    void doublyLinkedList<T>::removeByElement(const T &element)
    {
        removeByIndex(indexOf(element));
    }
    
    template <typename T>
    void doublyLinkedList<T>::add(const T &element)
    {
        add(this->listSize, element);
    }
    
    // 在指定索引处添加元素
    template <typename T>
    void doublyLinkedList<T>::add(int index, const T &element)
    {
        if (index < 0 || index > this->listSize)
        {
            std::ostringstream s;
            s << "index = " << index << "size = " << this->listSize;
            throw illegalIndex(s.str());
        }
    
        if (index == 0)
        { // 头部插入元素
            this->firstNode = new Node<T>(element, nullptr, this->firstNode);
        }
        else
        {
            Node<T> *p = this->firstNode;
            for (int i = 0; i < index - 1; i++)
            {
                p = p->next;
            }
            p->next = new Node<T>(element, p->prev, p->next);
        }
        this->listSize++;
    }
    
    template <typename T>
    void doublyLinkedList<T>::clear()
    {
        while (this->firstNode != nullptr)
        {
            Node<T> *nextNode = this->firstNode->next;
            delete this->firstNode;
            this->firstNode = nextNode;
        }
        this->firstNode = this->lastNode = nullptr;
        this->listSize = 0;
    }
    
    template <typename T>
    void doublyLinkedList<T>::output(std::ostream &out) const
    {
        for (Node<T> *currentNode = this->firstNode;
             currentNode != nullptr;
             currentNode = currentNode = currentNode->next)
            out << currentNode->element << " ";
    }
    
    // 重载 << 运算符
    template <typename T>
    std::ostream &operator<<(std::ostream &out, const doublyLinkedList<T> &list)
    {
        list.output(out);
        return out;
    }
    
    #endif
    

    测试(testDoublyLinkedList.cpp)

    /*************************************************************************
    > File Name       : testDoublyLinkedList.cpp
    > Author          : Harold
    > Mail            : 2106562095@qq.com
    > Github          : www.github.com/Haroldcc
    > Created Time    : 2020年02月28日  20时38分11秒
    ************************************************************************/
    #include <iostream>
    #include "linearList.h"
    #include "doublyLinkedList.h"
    
    using namespace std;
    
    int main()
    {
        doublyLinkedList<int> list;
    
        list.add(1);
        list.add(2);
    
        cout << list << endl;
    
        // test constructor
        linearList<double> *x = new doublyLinkedList<double>;
        doublyLinkedList<int> y, z;
    
        // test size
        cout << "Initial size of x, y, and z = "
             << x->size() << ", "
             << y.size() << ", "
             << z.size() << endl;
    
        // test isEmpty
        if (x->isEmpty())
            cout << "x is isEmpty" << endl;
        else
            cout << "x is not isEmpty" << endl;
        if (y.isEmpty())
            cout << "y is isEmpty" << endl;
        else
            cout << "y is not isEmpty" << endl;
    
        // test add
        y.add(0, 2);
        y.add(1, 6);
        y.add(0, 1);
        y.add(2, 4);
        y.add(3, 5);
        y.add(2, 3);
        cout << "Inserted 6 integers, list y should be 1 2 3 4 5 6" << endl;
        cout << "Size of y = " << y.size() << endl;
        if (y.isEmpty())
            cout << "y is isEmpty" << endl;
        else
            cout << "y is not isEmpty" << 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 getElement
        cout << "Element with index 0 is " << y.getElement(0) << endl;
        cout << "Element with index 3 is " << y.getElement(3) << endl;
    
        // test removeByIndex
        y.removeByIndex(1);
        cout << "Element 1 erased" << endl;
        cout << "The list is " << y << endl;
        y.removeByIndex(2);
        cout << "Element 2 erased" << endl;
        cout << "The list is " << y << endl;
        y.removeByIndex(0);
        cout << "Element 0 erased" << endl;
        cout << "The list is " << y << endl;
    
        cout << "Size of y = " << y.size() << endl;
        if (y.isEmpty())
            cout << "y is isEmpty" << endl;
        else
            cout << "y is not isEmpty" << endl;
    
        try
        {
            y.add(-3, 0);
        }
        catch (illegalIndex e)
        {
            cout << "Illegal index exception" << endl;
            cout << "Insert index must be between 0 and list size" << endl;
            e.outputMessage();
        }
    
        
        // a few more inserts, just for fun
        y.add(0, 4);
        y.add(0, 5);
        y.add(0, 6);
        y.add(0, 7);
        cout << "y is " << y << endl;
    
        y.clear();
    
        return 0;
    }
    

    输出

    1 2 
    Initial size of x, y, and z = 0, 0, 0
    x is isEmpty
    y is isEmpty
    Inserted 6 integers, list y should be 1 2 3 4 5 6
    Size of y = 6
    y is not isEmpty
    1 2 3 4 5 6
    Testing overloaded <<
    1 2 3 4 5 6
    The index of 4 is 3
    7 not found
    Element with index 0 is 1
    Element with index 3 is 4
    Element 1 erased
    The list is 1 3 4 5 6
    Element 2 erased
    The list is 1 3 5 6
    Element 0 erased
    The list is 3 5 6
    Size of y = 3
    y is not isEmpty
    Illegal index exception
    Insert index must be between 0 and list size     
    index = -3size = 3
    y is 7 6 5 4 3 5 6
    
  • 相关阅读:
    ubuntu十年
    国内开源镜像站
    vi 配置文件
    如何查看Linux命令源代码
    gedit乱码问题的解决
    Linux启动项修复
    我写新年愿望
    SEGGER J-Link 弹窗 在altium designer中禁用USBJATG
    线缆测试,手机端程序说明
    养兔场 网站上的个人介绍
  • 原文地址:https://www.cnblogs.com/HaroldC/p/12437381.html
Copyright © 2020-2023  润新知