LinkList (双向链表C++的实现,含内置迭代器的实现)

本文详细介绍了一种双向链表的模板类实现方法,包括链表节点(LinkNode)的定义,链表类(LinkList)的构造与成员函数,以及内部迭代器的实现。通过C++模板和迭代器,提供了链表的增删改查、排序和合并等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 LinkNode(链表节点):

#pragma once
#include"Comparetor.h"
/*
*双向链表(模板类实现)
*作者:问月晚安
*时间:19-8-15
*/
/*定义链表节点*/
template<typename T>
struct ListNode{
    ListNode* next;   //后继节点
    ListNode* prev;   //前驱节点
    T element;        //节点元素
};

链表实际上是一堆节点的集合,它可以是一个抽象的概念,封装了对这些节点的操作。

所以我们首先需要动手编写的就是它的基本单元,链表节点(LinkNode)


 

LinkList(链表模板类):

下面是LinkList类的说明,实现了基本的针对集合的增删改查。相信大家实现起来都不会有什么问题,只需要注意一下链表节点指针域赋值时的指向即可。

用过C++集合类的朋友应该知道,每一个集合类都有一个配套的内置迭代器,我这里也实现了它。很显然这个迭代器是一个内部类,不过C++对内部类似乎并不怎么上心,因为当你在外部使用内部类作为形参类型、函数返回值类型。。。时,你必须typename告诉编译器它是一个类型。

/*定义链表类*/
template<typename T>
class LinkList{
private:
    ListNode<T>* head;   //表头节点
    ListNode<T>* tail;   //表尾节点
    int size;            //链表长度

public:

    /***********CREATE***********/
    LinkList();                                      //无参构造函数(空链表)
    LinkList(const LinkList<T>& linklist);           //重载拷贝构造函数
    LinkList(int size,T elment);                     //有参构造函数(初始长度的链表)
    LinkList<T>& operator=(const LinkList<T>& linklist);//重载赋值函数

    /**********DESTORY**********/
    ~LinkList();            //析构函数
    void Destory();            //销毁函数

    /**********ISTHING**********/
    bool isEmpty()const;            //是否为空链表

    /************GET************/
    int getSize()const;                //获取链表长度
    ListNode<T>* getHead()const;            //获取头节点
    ListNode<T>* getTail()const;            //获取尾节点

    T getElemOfHead()const;                //获取头节点的元素值
    T getElemOfTail()const;                //获取尾节点的元素值
    T getElemOfIndex(int index)const;    //获取指定下标节点的元素值

    /***********SET*************/
    LinkList<T>* setElemOfHead(T element);                //修改头节点元素
    LinkList<T>* setElemOfTail(T element);                //修改尾节点元素
    LinkList<T>* setElemOfIndex(int index, T element);    //修改指定节点元素


    /************ADD************/
    LinkList<T>* InsertToTail(T element);                //添加节点到尾部
    LinkList<T>* InsertToHead(T element);                //添加节点到头部
    LinkList<T>* InsertOfIndex(int index, T element);    //添加节点到指定下标元素的后面

    /***********DELETE**********/
    LinkList<T>* deleteOfIndex(int index);            //删除指定下标元素
    LinkList<T>* deleteToTail();                    //删除尾节点元素
    LinkList<T>* deleteToHead();                    //删除头节点元素

    /************SORT***********/
    LinkList<T>* sort(Comparator<T>* comparator);        //排序(根据比较器排序)
    LinkList<T>* sort();                                //重载运算符-排序

    /**********CONNECT*********/
    LinkList<T>* connect(LinkList<T>* linklist);        //链表合并


    /********ITERATOR********/
    class Iterator{
    private:
        ListNode<T>* i_PtrNode;                        //迭代器指针当前指向的节点

    public:
        ListNode<T>* getListNode();                    //获取当前节点
        Iterator(ListNode<T>* tmpNode = nullptr);    
        T operator*() const;
        ListNode<T>* operator->() const;
        Iterator& operator++();
        Iterator operator++(int);
        Iterator& operator--();
        Iterator operator--(int);
        bool operator==(const Iterator& other) const;
        bool operator!=(const Iterator& other) const;
    };

    typename Iterator begin();                    //返回一个指向头节点的迭代器
    typename Iterator end();                    //返回一个指向尾节点的迭代器
    typename Iterator over();                    //返回一个指向边界的迭代器
    void erase(typename Iterator& iter);        //删除指定迭代器指针指向的元素
};

这里需要补充点说明:

在C++的迭代器中,end()表示的是最后一个元素的指向的下一个元素的指针。而我这里因为是双向链表为了能直接获取到尾部迭代器所以增加了over()代替end(),而end()将返回指向末尾迭代器。

另外不像Java,C++的泛型机制并不具有协变的能力,这意味着你无法限定模板参数的类型。所以当你实现诸如排序等需要提供比较器的功能的时候,你就必须提供相应的接口或者重载相应运算符。不过C++这种机制不是没有好处,虽然增加了代码量但是分离了职责。

还有一点就是重载拷贝构造和赋值函数,这是很有必要的一件事情当你类中有指针指向堆区内存并且你将在析构函数中释放它时。


功能实现:

迭代器功能:

对于迭代器,从设计的角度上讲是为了分离职责,从功能上来讲是为了方便对于集合的增删改查操作

所以你能看到它的实现都是重载了一些运算符,这使它用起来就像是操作指针一样方便,而这也是设计迭代器的本意。

/*********************迭代器内部类函数实现**************************/

/*获取当前迭代器的节点*/
template<typename T>
ListNode<T>* LinkList<T>::Iterator::getListNode(){
    return i_PtrNode;
}

/*构造函数*/
template<typename T>
LinkList<T>::Iterator::Iterator(ListNode<T>* tmpNode = nullptr){
    i_PtrNode = tmpNode;
};

/*解引用运算符重载*/
template<typename T>
T LinkList<T>::Iterator::operator*()const{
    if (i_PtrNode!=nullptr)
        return i_PtrNode->element;
    return T(0);
}

/*指针箭头运算符重载*/
template<typename T>
ListNode<T>* LinkList<T>::Iterator::operator->() const{
    if (i_PtrNode !=nullptr)
        return i_PtrNode;
    return nullptr;
}

/*前置++重载*/
template<typename T>
typename LinkList<T>::Iterator& LinkList<T>::Iterator::operator++(){
    if (i_PtrNode != nullptr){
        i_PtrNode = i_PtrNode->next;
        return *this;
    }
    return Iterator(nullptr);
}

/*后置++重载*/
template<typename T>
typename LinkList<T>::Iterator LinkList<T>::Iterator::operator++(int){
    if (i_PtrNode != nullptr){
        ListNode<T>* tmpNode = i_PtrNode;
        i_PtrNode = i_PtrNode->next;
        return Iterator(tmpNode);
    }
    return Iterator(nullptr);
}

/*前置--重载*/
template<typename T>
typename LinkList<T>::Iterator& LinkList<T>::Iterator::operator--(){
    if (i_PtrNode != nullptr){
        i_PtrNode = i_PtrNode->prev;
        return *this;
    }
    return Iterator(nullptr);
}

/*后置--重载*/
template<typename T>
typename LinkList<T>::Iterator LinkList<T>::Iterator::operator--(int){
    if (i_PtrNode != nullptr){
        ListNode<T>* tmpNode = i_PtrNode;
        i_PtrNode = i_PtrNode->prev;
        return Iterator(tmpNode);
    }
    return Iterator(nullptr);
}

/*重载等号运算符*/
template<typename T>
bool LinkList<T>::Iterator::operator==(const Iterator& other) const{
    return (this->i_PtrNode == other.i_PtrNode);
}

/*重载不等号运算符*/
template<typename T>
bool LinkList<T>::Iterator::operator!=(const Iterator& other) const{
    return (this->i_PtrNode != other.i_PtrNode);
}

 


 

LinkList(链表功能实现):

实际上我在这里实现功能的时候有点冗余,因为方便版述在博客上,很多应该实现在迭代器上的功能被我实现在链表功能里。

另外有一种简单的实现方式,就是增加辅助头节点和尾节点,这样你的链表中就会始终存在分配了内存的头尾节点,当你进行操作时不需要考虑端点问题。

/**************************链表内部函数实现*******************************/

/*获取指向头节点的迭代器*/
template<typename T>
typename LinkList<T>::Iterator LinkList<T>::begin(){
    return Iterator(head);
}

/*获取指向尾节点的迭代器*/
template<typename T>
typename LinkList<T>::Iterator LinkList<T>::end(){
    return Iterator(tail);
}

/*获取指向边界的迭代器*/
template<typename T>
typename LinkList<T>::Iterator LinkList<T>::over(){
    return Iterator(tail->next);
}

/*删除指定迭代器指针的节点*/
template<typename T>
void LinkList<T>::erase(typename LinkList<T>::Iterator& iter){
    if (isEmpty())
        return;
    if (iter == over())
        return;
    
    ListNode<T>* tmpListNode = iter.getListNode();

    if (head == tail){
        head = tail = tmpListNode->next;
    }
    else if (head == tmpListNode){
        head = tmpListNode->next;
        head->prev = nullptr;
    }
    else if (tail == tmpListNode){
        tail = tmpListNode->prev;
        tail->next = nullptr;
    }
    else{
        tmpListNode->next->prev = tmpListNode->prev;
        tmpListNode->prev->next = tmpListNode->next;
    }
    iter++;
    delete tmpListNode;
    size--;

}


/*无参构造函数(创建空链表)*/
template<typename T>
LinkList<T>::LinkList(){
    tail = head = nullptr;
    size = 0;
};

/*有参构造函数(创建指定长度的链表,并全部赋值为element)*/
template<typename T>
LinkList<T>::LinkList(int size, T element){
    for (int i = 0; i < size; i++){
        ListNode<T>* newListNode = new ListNode<T>;
        newListNode->element = element;
        newListNode->next = nullptr;
        if (i == 0){
            newListNode->prev = nullptr;
            tail = head = newListNode;
        }
        else{
            newListNode->prev = tail;
            tail->next = newListNode;
            tail = newListNode;
        }
    }
    this->size = size;
};

/*赋值函数重载*/
template<typename T>
LinkList<T>& LinkList<T>::operator=(const LinkList<T>& linklist){
    if (this == &linklist)
        return *this;

    this->Destory();
    this->size = 0;
    if (linklist->head == nullptr)
        return *this;

    ListNode<T>* tmpNode = linklist->head;
    while (tmpNode){
        ListNode<T>* newNode = new ListNode<T>;
        newNode->next = nullptr;
        newNode->element = tmpNode->element;
        if (this->head == nullptr){
            newNode->prev = nullptr;
            head = tail = newNode;
        }
        else{
            tail->next = newNode;
            newNode->prev = tail;
            tail = newNode;
        }
        tmpNode = tmpNode->next;
    }
    this->size = linklist->size;
    return *this;
}

/*拷贝构造函数*/
template<typename T>
LinkList<T>::LinkList(const LinkList<T>& linklist){
    head = tail = nullptr;
    size = 0;
    if (linklist.head == nullptr)
        return;

    ListNode<T>* tmpNode = linklist.head;
    while (tmpNode){
        ListNode<T>* newNode = new ListNode<T>;
        newNode->next = nullptr;
        newNode->element = tmpNode->element;
        if (this->head == nullptr){
            newNode->prev = nullptr;
            head = tail = newNode;
        }
        else{
            newNode->prev = tail;
            tail->next = newNode;
            tail = newNode;
        }
        tmpNode = tmpNode->next;
    }
}

/*析构函数(调用销毁函数)*/
template<typename T>
LinkList<T>::~LinkList(){
    Destory();
};

/*销毁函数(释放节点内存)*/
template<typename T>
void LinkList<T>::Destory(){
    ListNode<T>* tmpListNode = head;
    while (head){
        tmpListNode = tmpListNode->next;
        delete head;
        head = tmpListNode;
    }
}

/*判断是否为空*/
template<typename T>
bool LinkList<T>::isEmpty()const{
    if (size == 0)
        return true;
    return false;
}

/*获取链表长度*/
template<typename T>
int LinkList<T>::getSize()const{
    return size;
}

/*获取头节点*/
template<typename T>
ListNode<T>* LinkList<T>::getHead()const{
    return head;
}

/*获取尾节点*/
template<typename T>
ListNode<T>* LinkList<T>::getTail()const{
    return tail;
}

/*获取头节点元素*/
template<typename T>
T LinkList<T>::getElemOfHead()const{
    if (isEmpty())
        return T(0);
    return head->element;
}

/*获取尾节点元素*/
template<typename T>
T LinkList<T>::getElemOfTail()const{
    if (isEmpty())
        return T(0);
    return tail->element;
}

/*获取指定下标节点元素*/
template<typename T>
T LinkList<T>::getElemOfIndex(int index)const{
    if (isEmpty())
        return T(0);
    ListNode<T>* tmpListNode = head;
    for (int i = 0; i < size; i++){
        if (i == index)
            return tmpListNode->element;
        tmpListNode = tmpListNode->next;
    }
    return T(0);
}

/*设置头节点元素*/
template<typename T>
LinkList<T>* LinkList<T>::setElemOfHead(T element){
    if (isEmpty())
        return nullptr;
    head->element = element;
    return this;
}

/*设置尾节点元素*/
template<typename T>
LinkList<T>* LinkList<T>::setElemOfTail(T element){
    if (isEmpty())
        return nullptr;
    tail->element = element;
    return this;
}

/*设置指定下标节点元素*/
template<typename T>
LinkList<T>* LinkList<T>::setElemOfIndex(int index, T element){
    if (isEmpty())
        return nullptr;
    ListNode<T>* tmpListNode = head;
    for (int i = 0; i < size; i++){
        if (i == index)
            tmpListNode->element = element;
        tmpListNode = tmpListNode->next;
    }
    return this;
}

/*添加尾部节点*/
template<typename T>
LinkList<T>* LinkList<T>::InsertToTail(T element){
    ListNode<T>* newListNode = new ListNode<T>;
    newListNode->element = element;
    newListNode->next = nullptr;
    newListNode->prev = tail;
    if (isEmpty()){
        tail = newListNode;
        head = tail;
    }
    else{
        tail->next = newListNode;
        tail = newListNode;
    }
    size++;
    return this;
}

/*添加头部节点*/
template<typename T>
LinkList<T>* LinkList<T>::InsertToHead(T element){
    ListNode<T>* newListNode = new ListNode<T>;
    newListNode->element = element;
    newListNode->next = head;
    newListNode->prev = nullptr;
    if (isEmpty()){
        head = newListNode;
        tail = head;
    }
    else{
        head->prev = newListNode;
        head = newListNode;
    }
    size++;
    return this;
}

/*添加指定下标的节点*/
template<typename T>
LinkList<T>* LinkList<T>::InsertOfIndex(int index, T element){
    if (isEmpty() && index != 0)
        return nullptr;
    ListNode<T>* tmpListNode = head;
    for (int i = 0; i < size; i++){
        if (i == index){
            ListNode<T>* newListNode = new ListNode<T>;
            newListNode->prev = tmpListNode;
            newListNode->element = element;

            if (isEmpty()){    //为空链表时
                newListNode->next = nullptr;
                head = tail = newListNode;
            }
            else if(i == size - 1){    //从尾部添加时
                newListNode->next = nullptr;
                tmpListNode->next = newListNode;
                tail = newListNode;
                
            }
            else{    //从中间位置添加时
                newListNode->next = tmpListNode->next;
                tmpListNode->next->prev = newListNode;
                tmpListNode->next = newListNode;
            }
            size++;
            return this;
        }
        tmpListNode = tmpListNode->next;
    }
}

/*删除指定下标的节点*/
template<typename T>
LinkList<T>* LinkList<T>::deleteOfIndex(int index){
    if (isEmpty())
        return nullptr;
    ListNode<T>* tmpListNode = head;
    for (int i = 0; i < size; i++){
        if (i == index){
            if (i == 0){    //删除的是头部节点时
                tmpListNode->next->prev = tmpListNode->prev;
                head = tmpListNode->next;
            }
            else if (i == size - 1){    //删除的是尾部节点时
                tmpListNode->prev->next = tmpListNode->next;
                tail = tmpListNode->prev;
            }
            else{
                tmpListNode->next->prev = tmpListNode->prev;
                tmpListNode->prev->next = tmpListNode->next;
            }
            delete tmpListNode;
            size--;
            return this;
        }
        tmpListNode = tmpListNode->next;
    }

}

/*删除尾节点*/
template<typename T>
LinkList<T>* LinkList<T>::deleteToTail(){
    if (isEmpty())
        return nullptr;
    ListNode<T>* tmpListNode = tail;
    tail = tail->prev;
    if (size == 1){
        head = tail;
    }
    else{
        tail->next = nullptr;
    }
    delete tmpListNode;
    size--;
    return this;
}

/*删除头节点*/
template<typename T>
LinkList<T>* LinkList<T>::deleteToHead(){
    if (isEmpty())
        return nullptr;
    ListNode<T>* tmpListNode = head;
    head = head->next;
    if (size == 1){
        tail = head;
    }
    else{
        head->prev = nullptr;
    }
    delete tmpListNode;
    size--;
    return this;
}

/*比较器-排序*/
template<typename T >
LinkList<T>* LinkList<T>::sort(Comparator<T>* comparator){
    if (isEmpty())
        return nullptr;
    for (int i = 0; i < size - 1; i++){
        ListNode<T>* tmpListNode = head;
        for (int j = i + 1; j < size; j++){
            if (comparator->compare(tmpListNode->element, tmpListNode->next->element)){
                T tmp_element = tmpListNode->element;
                tmpListNode->element = tmpListNode->next->element;
                tmpListNode->next->element = tmp_element;
            }
            tmpListNode = tmpListNode->next;
        }
    }
    return this;
}

/*重载运算符-排序*/
template<typename T>
LinkList<T>* LinkList<T>::sort(){
    if (isEmpty())
        return nullptr;
    for (int i = 0; i < size - 1; i++){
        ListNode<T>* tmpListNode = head;
        for (int j = i + 1; j < size; j++){
            if (tmpListNode->element > tmpListNode->next->element){
                T tmp_element = tmpListNode->element;
                tmpListNode->element = tmpListNode->next->element;
                tmpListNode->next->element = tmp_element;
            }
            tmpListNode = tmpListNode->next;
        }
    }
    return this;
}

/*链表合并*/
template<typename T>
LinkList<T>* LinkList<T>::connect(LinkList<T>* linklist){
    ListNode<T>* tnpListNode = this->getTail();
    ListNode<T>* tmpListNode = linklist->getHead();
    while (tmpListNode){
        ListNode<T>* newListNode = new ListNode<T>;
        newListNode->next = nullptr;
        newListNode->element = tmpListNode->element;
        if (this->tail == nullptr){
            newListNode->prev = nullptr;
            this->head = this->tail = tmpListNode;
        }
        else{
            tail->next = newListNode;
            newListNode->prev = tail;
            tail = newListNode;
        }
        tmpListNode = tmpListNode->next;
    }
    size += linklist->getSize();
    return this;
}

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值