diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index a247b178..1dbcdc60 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -165,6 +165,140 @@ private: ## 其他语言版本 +### C++双链表法: + +```CPP +//采用循环虚拟结点的双链表实现 +class MyLinkedList { +public: + // 定义双向链表节点结构体 + struct DList { + int elem; // 节点存储的元素 + DList *next; // 指向下一个节点的指针 + DList *prev; // 指向上一个节点的指针 + // 构造函数,创建一个值为elem的新节点 + DList(int elem) : elem(elem), next(nullptr), prev(nullptr) {}; + }; + + // 构造函数,初始化链表 + MyLinkedList() { + sentinelNode = new DList(0); // 创建哨兵节点,不存储有效数据 + sentinelNode->next = sentinelNode; // 哨兵节点的下一个节点指向自身,形成循环 + sentinelNode->prev = sentinelNode; // 哨兵节点的上一个节点指向自身,形成循环 + size = 0; // 初始化链表大小为0 + } + + // 获取链表中第index个节点的值 + int get(int index) { + if (index > (size - 1) || index < 0) { // 检查索引是否超出范围 + return -1; // 如果超出范围,返回-1 + } + int num; + int mid = size >> 1; // 计算链表中部位置 + DList *curNode = sentinelNode; // 从哨兵节点开始 + if (index < mid) { // 如果索引小于中部位置,从前往后遍历 + for (int i = 0; i < index + 1; i++) { + curNode = curNode->next; // 移动到目标节点 + } + } else { // 如果索引大于等于中部位置,从后往前遍历 + for (int i = 0; i < size - index; i++) { + curNode = curNode->prev; // 移动到目标节点 + } + } + num = curNode->elem; // 获取目标节点的值 + return num; // 返回节点的值 + } + + // 在链表头部添加节点 + void addAtHead(int val) { + DList *newNode = new DList(val); // 创建新节点 + DList *next = sentinelNode->next; // 获取当前头节点的下一个节点 + newNode->prev = sentinelNode; // 新节点的上一个节点指向哨兵节点 + newNode->next = next; // 新节点的下一个节点指向原来的头节点 + size++; // 链表大小加1 + sentinelNode->next = newNode; // 哨兵节点的下一个节点指向新节点 + next->prev = newNode; // 原来的头节点的上一个节点指向新节点 + } + + // 在链表尾部添加节点 + void addAtTail(int val) { + DList *newNode = new DList(val); // 创建新节点 + DList *prev = sentinelNode->prev; // 获取当前尾节点的上一个节点 + newNode->next = sentinelNode; // 新节点的下一个节点指向哨兵节点 + newNode->prev = prev; // 新节点的上一个节点指向原来的尾节点 + size++; // 链表大小加1 + sentinelNode->prev = newNode; // 哨兵节点的上一个节点指向新节点 + prev->next = newNode; // 原来的尾节点的下一个节点指向新节点 + } + + // 在链表中的第index个节点之前添加值为val的节点 + void addAtIndex(int index, int val) { + if (index > size) { // 检查索引是否超出范围 + return; // 如果超出范围,直接返回 + } + if (index <= 0) { // 如果索引为0或负数,在头部添加节点 + addAtHead(val); + return; + } + int num; + int mid = size >> 1; // 计算链表中部位置 + DList *curNode = sentinelNode; // 从哨兵节点开始 + if (index < mid) { // 如果索引小于中部位置,从前往后遍历 + for (int i = 0; i < index; i++) { + curNode = curNode->next; // 移动到目标位置的前一个节点 + } + DList *temp = curNode->next; // 获取目标位置的节点 + DList *newNode = new DList(val); // 创建新节点 + curNode->next = newNode; // 在目标位置前添加新节点 + temp->prev = newNode; // 目标位置的节点的前一个节点指向新节点 + newNode->next = temp; // 新节点的下一个节点指向目标位置的结点 + newNode->prev = curNode; // 新节点的上一个节点指向当前节点 + } else { // 如果索引大于等于中部位置,从后往前遍历 + for (int i = 0; i < size - index; i++) { + curNode = curNode->prev; // 移动到目标位置的后一个节点 + } + DList *temp = curNode->prev; // 获取目标位置的节点 + DList *newNode = new DList(val); // 创建新节点 + curNode->prev = newNode; // 在目标位置后添加新节点 + temp->next = newNode; // 目标位置的节点的下一个节点指向新节点 + newNode->prev = temp; // 新节点的上一个节点指向目标位置的节点 + newNode->next = curNode; // 新节点的下一个节点指向当前节点 + } + size++; // 链表大小加1 + } + + // 删除链表中的第index个节点 + void deleteAtIndex(int index) { + if (index > (size - 1) || index < 0) { // 检查索引是否超出范围 + return; // 如果超出范围,直接返回 + } + int num; + int mid = size >> 1; // 计算链表中部位置 + DList *curNode = sentinelNode; // 从哨兵节点开始 + if (index < mid) { // 如果索引小于中部位置,从前往后遍历 + for (int i = 0; i < index; i++) { + curNode = curNode->next; // 移动到目标位置的前一个节点 + } + DList *next = curNode->next->next; // 获取目标位置的下一个节点 + curNode->next = next; // 删除目标位置的节点 + next->prev = curNode; // 目标位置的下一个节点的前一个节点指向当前节点 + } else { // 如果索引大于等于中部位置,从后往前遍历 + for (int i = 0; i < size - index - 1; i++) { + curNode = curNode->prev; // 移动到目标位置的后一个节点 + } + DList *prev = curNode->prev->prev; // 获取目标位置的下一个节点 + curNode->prev = prev; // 删除目标位置的节点 + prev->next = curNode; // 目标位置的下一个节点的下一个节点指向当前节点 + } + size--; // 链表大小减1 + } + +private: + int size; // 链表的大小 + DList *sentinelNode; // 哨兵节点的指针 +}; +``` + ### C: ```C