C++数据结构【01】——链表

一、定义

链表是数据结构中,最简单的一种数据结构。简单到你可以将它看成一个数组,只不过这个数组元素不像常规数组那样内存连续,而是类似于一根链条,被某些东西给连接起来。

单链表

单链表由一系列不必在内存中相连的结构组成,每一个结构均含有表元素和指向包含该元素的后继元的结构的指针。

next
next
next
NodeA
NodeB
NodeC
...
NULL

上图为链表的基本结构图,最后一个元素...的后继元为NULL

删除节点

单链表删除节点相当简单,只需要更改被删节点的前驱元的next指针,指向被删节点的后继元,即可完成节点的删除工作。如下图所示:

next
next
next
next
NodeA
NodeB
NodeC
...
NULL

上图中,节点NodeB是被删节点,因此只需要将节点NodeAnext指针指向节点NodeC即可。

增加节点

next
next
next
NodeA
NodeB
NodeD
NodeC
...
NULL

上图中,要在节点NodeA和节点NodeB中间插入节点NodeD,只需要将NodeA的next指针指向节点NodeD,同时将节点NodeD的next指针指向节点NodeB即可。

双链表

双链表是在单链表的基础上,增加一个指向上一个节点的指针。这样做的好处是,对于倒序遍历链表,实现方式相当简单。

双链表的图示如下:

next
previous
next
previous
next
previous
NodeA
NodeB
NodeC
...
NULL

循环链表

循环链表则是在单/双链表的基础上进一步扩展,将原本表尾指向NULL的指针,换成指向表头节点。

循环链表(双链表)图示如下:

next
previous
previous
next
previous
next
previous
next
NodeA
NodeB
...
NodeC

二、实现

节点(Node)

节点是表形数据结构中的基本单元,甚至也是树形数据结构的基本单元。以下代码定义一个简单的节点类型:

template <typename T>
class Node
{
public:
    Node(T *entity = nullptr) : m_pEntity(entity) {}
    virtual ~Node() = 0 {}

    /**
     * @brief 设置节点的数据
     * 
     * @param ent 新的节点数据
     */
    void setEntity(T *ent) { m_pEntity = ent; }

    /**
     * @brief 获取节点的数据
     * 
     * @return T* 节点的数据
     */
    T *entity() { return m_pEntity; }

protected:
    // 节点的数据域
    T *m_pEntity;
};

单链表

/**
 * @brief 单链表类。
 * 
 * @tparam T 
 */
template<typename T>
class SingleLinkedList
{
public:
    SingleLinkedList() : m_pHead(nullptr), m_pTail(nullptr) {}
    SingleLinkedList(const SingleLinkedList &rhs) : m_pHead(rhs.m_pHead), m_pTail(rhs.m_pTail) {}
    ~SingleLinkedList() {}

    /**
     * @brief 构造一个空的单链表。
     * 
     * @return SingleLinkedList<T>* 构造出来的空单链表
     */
    static SingleLinkedList<T>* constructEmpty()
    {
        SingleLinkedList<T> *ret = new SingleLinkedList<T>;
        return ret;
    }

    SingleListNode<T> *head() { return m_pHead; }
    bool empty() { return m_pHead == m_pTail; }

    // 单链表的插入操作
    void insert(T *ent, SingleListNode<T>* pos)
    {
        if(! pos)
            return;
        SingleListNode<T> newNode = new SingleListNode<T>(ent);
        auto next = pos->next();
        // 将当前节点的next指针指向新节点
        pos->setNext(newNode);
        // 再将新节点的next指针指向原本的next节点。
        newNode->setNext(next);
        // 如此就完成了节点的插入操作
    }

    // 单链表的删除操作
    void deleteNode(T* ent)
    {
        if(m_pHead && m_pHead->entity() == ent)
        {
            m_pHead = m_pHead->next();
            return;
        }
        // 由于单链表没有记录上一个节点的指针,因此这里使用双指针的方式,来进行单链表
        // 节点的删除操作。
        SingleListNode<T> *previous = m_pHead;
        SingleListNode<T> *current = m_pHead->next();
        while (current)
        {
            if(current->entity() == ent)
            {
                // 如果当前节点的数据对象就是要删除的数据对象,
                // 则直接将当前节点的上一级节点的next指针,指向当前节点的下一级节点。
                previous->setNext(current->next());
                break;
            }
            previous = current;
            current = current->next();
        }
        
    }

    // 单链表的查找操作
    SingleListNode<T>* findPrevious(T* ent)
    {
        SingleListNode<T> *cur = m_pHead;
        while (cur)
        {
            if(cur->entity() == ent)
                return cur;
            cur = cur->next();
        }
    }

protected:
    SingleListNode<T> *m_pHead;
    SingleListNode<T> *m_pTail;
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

geocat

球球大佬们赏赐点吃喝!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值