双向列表的实现(C++)

一.实现思路

主要是一个空间存储一个数值,然后为了索引后面的数据单元和前面的数据单元,所以在每个空间里面还要存储前面和后面数据单元的指针,就形成了每个数据单元

后面就是要管理的是双向列表的头结点和尾节点,方便实现后面的头插和尾插

template <typename T>

class DoubleList

{

Node<T>* head;

Node<T>* tail;

}

这些就是一个双向列表的一个整体逻辑

二.增删查改的实现

复制代码
void insertAtEnd(T value);
    void insertAtBeginning(T value);
    void deleteNode(T value);
    Node<T>* find(T value);
    void printList();

我主要实现的就是这几个函数,但是其实再多也是一样的思路,就举个尾插来进行举例子

对于尾插而言,第一步肯定是先将这个节点进行实现,这个时候肯定是使用new来进行实现,因为使用new来实现的时候,空间是开在堆上的,方便后面析构函数进行空间清理, 否则出了这个函数对应的节点也会进行清空,十分鸡肋。

然后第二步是判断这个双向列表是不是空的,如果是空的就将头部和尾部都指向这个节点。如果不为空,则进行插入,也就是将tail变为现在这个节点,然后将前一个节点的后节点指针改为自己,将后一个节点的前一个指针改为自己,自己节点前后节点的指针也改为对应的节点。

void insertAtEnd(T value)

{

if (head == nullptr)

{

head = new Node<T>(value);

tail = head;

head->data = value;

head->prev = head;

head->next = head;

return;

}

node = new Node<T>(value);

tail->next = node;

node->prev = tail;

head->prev = node;

node->next = head;

tail = node;

}

而对于某个节点的查找,也是类似的情况,首先是判断这个双向列表是不是空的,如果是则返回nullptr,如果不是则对head和tail中的所有节点进行遍历,如果存在则返回对应节点,如果不存在则返回nullptr。

Node<T>* find(T value)

{

if (head == nullptr)

{

return nullptr;

}

for (node<T>* begin = head; begin != tail; begin = begin->next)

{

if (begin->data == value)

{

return begin;

}

}

if (begin->data == value)

{

return begin;

}

return nullptr;

}

对于节点的删除来说,就是将节点的查找加上节点前后的指针换位,然后将这个节点进行空间释放,就得到了节点删除的函数。但是在这之前我们要处理一系列特殊情况

void deleteNode(T value)

{

Node<T>* node = find(value);

if (node == nullptr)

{

return;

}

if (head == tail)

{

head->next = nullptr;

head->prev = nullptr;

return;

}

if (node == head)

{

head = head->next;

tail->next = head;

head->prev = tail;

delete node;

return;

}

if (node == tail)

{

tail = tail->prev;

head->prev = tail;

tail->next = head;

delete node;

return;

}

node->prev->next = node->next;

node->next->prev = node->prev;

delete node;

}

三.析构函数的实现

最后就是析构函数的实现了,因为我们前面利用了new开辟的很多的节点,所以就导致了后面这些空间肯定要我们自己手动释放,所以我们要写对应的析构函数,就是遍历每一个节点,然后遍历完以后将每一个节点进行释放,其中释放每一个节点之前一定要记得将后一个节点的指针记录下来

~DoublyLinkedList()

{

en = head->next;

for (it = head; it != tail; it = en)

{

en = it->next;

delete node;

}

delete node;

}

相关推荐
修炼前端秘籍的小帅9 分钟前
精读《JavaScript 高级程序设计 第4版》第6章 集合引用类型(三)Map、WeakMap、Set、WeakSet
开发语言·javascript·ecmascript
@LetsTGBot搜索引擎机器人22 分钟前
打造属于你的 Telegram 中文版:汉化方案 + @letstgbot 搜索引擎整合教程
开发语言·python·搜索引擎·机器人·.net
CS创新实验室28 分钟前
典型算法题解:长度最小的子数组
数据结构·c++·算法·考研408
我有一些感想……31 分钟前
浅谈 BSGS(Baby-Step Giant-Step 大步小步)算法
c++·算法·数论·离散对数·bsgs
人工智能的苟富贵31 分钟前
使用 Tauri + Rust 构建跨平台桌面应用:前端技术的新边界
开发语言·前端·rust·electron
j_xxx404_33 分钟前
C++ STL:string类(3)|operations|string类模拟实现|附源码
开发语言·c++
GHZero1 小时前
Java 之解读String源码(九)
java·开发语言
Swift社区1 小时前
Lombok 不生效 —— 从排查到可运行 Demo(含实战解析)
java·开发语言·安全
南清的coding日记1 小时前
Java 程序员的 Vue 指南 - Vue 万字速览(01)
java·开发语言·前端·javascript·vue.js·css3·html5
@大迁世界1 小时前
我用 Rust 重写了一个 Java 微服务,然后丢了工作
java·开发语言·后端·微服务·rust