📅  最后修改于: 2023-12-03 15:42:07.851000             🧑  作者: Mango
链表 (Linked List) 是一种数据结构,它由一系列节点组成。每个节点包含一个数据元素和一个指向下一个节点的指针。链表的头节点是第一个节点,尾节点是最后一个节点,它们分别指向 NULL 值。
常见的链表有单向链表、双向链表和循环链表。
链表的操作包括插入、删除、查找等,其在内存中的存储结构灵活,可以动态地分配内存空间,逐一将数据结点按照链式链接起来,因而解决了数组大小固定的缺陷。
链表的优缺点分别如下:
单向链表是链表中最简单的一种类型,其定义如下:
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
单向链表只有一个指针变量 next
,它记录下一个节点的地址。
单向链表的插入和删除方法:
// 在位置pos插入节点node
ListNode* insertNode(ListNode* head, ListNode* node, int pos) {
if (pos == 0) {
node->next = head;
return node;
}
ListNode* curr = head;
while (curr && pos > 1) {
curr = curr->next;
pos--;
}
if (curr) {
node->next = curr->next;
curr->next = node;
}
return head;
}
// 删除值为val的节点
ListNode* deleteNode(ListNode* head, int val) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* curr = dummy;
while (curr->next) {
if (curr->next->val == val) {
ListNode* tmp = curr->next;
curr->next = tmp->next;
delete tmp;
break;
} else {
curr = curr->next;
}
}
head = dummy->next;
delete dummy;
return head;
}
双向链表增加了一个指针变量 prev
,它记录上一个节点的地址。
双向链表的定义如下:
struct ListNode {
int val;
ListNode* prev;
ListNode* next;
ListNode(int x) : val(x), prev(nullptr), next(nullptr) {}
};
双向链表的插入和删除方法:
// 在位置pos插入节点node
ListNode* insertNode(ListNode* head, ListNode* node, int pos) {
if (pos == 0) {
node->next = head;
if (head) head->prev = node;
return node;
}
ListNode* curr = head;
while (curr && pos > 1) {
curr = curr->next;
pos--;
}
if (curr) {
node->next = curr->next;
node->prev = curr;
if (curr->next) curr->next->prev = node;
curr->next = node;
}
return head;
}
// 删除值为val的节点
ListNode* deleteNode(ListNode* head, int val) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
if (head) head->prev = dummy;
ListNode* curr = dummy;
while (curr->next) {
if (curr->next->val == val) {
ListNode* tmp = curr->next;
curr->next = tmp->next;
if (tmp->next) tmp->next->prev = curr;
delete tmp;
break;
} else {
curr = curr->next;
}
}
head = dummy->next;
if (head) head->prev = nullptr;
delete dummy;
return head;
}
循环链表和单向链表、双向链表的区别在于尾节点指向头节点。
循环链表的定义如下:
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
循环链表的插入和删除方法与单向链表相同。