更新0707.设计链表 新增CPP版本的双链表

This commit is contained in:
ForsakenDelusion
2024-07-06 11:15:55 +08:00
committed by GitHub
parent 27946081cc
commit 72c1db1c8a

View File

@ -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