2.1 链表理论基础
链接:文章
单链表:一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针)。
双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点,既可以向前查询也可以向后查询。
循环链表:链表首尾相连。
链表存储方式:非连续分布,散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。
链表的定义:
// 单链表
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数
};
链表的操作:删除节点,增加节点
2.2 移除链表元素
链接:文章;视频;203.移除链表元素
直接删除法:分删除节点为头节点和非头节点两种情况
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
// 删除头节点
while (head != NULL && head->val == val) {
head = head->next;
}
// 删除非头节点
ListNode* cur = head;
while (cur != NULL && cur->next != NULL) {
if (cur->next->val == val){
cur->next = cur->next->next;
} else {
cur = cur->next;
}
}
return head;
}
};
设置虚拟头节点
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0); // 设置虚拟头节点
dummyHead->next = head;
ListNode* cur = dummyHead;
while (cur->next != NULL) {
if (cur->next->val == val) {
cur->next = cur->next->next;
} else {
cur = cur->next;
}
}
return dummyHead->next;
}
};
2.3 设计链表
class MyLinkedList {
private:
// 定义链表节点结构体
struct ListNode {
int val;
ListNode* next;
ListNode(int val):val(val), next(nullptr) {}
};
int len;
ListNode* dummyHead;
public:
MyLinkedList() {
len = 0; // 初始化链表长度
dummyHead = new ListNode(0); // 设置虚拟头节点
}
int get(int index) {
if (index < 0 || index > (len - 1)) {
return -1;
}
ListNode* head = dummyHead->next;
ListNode* cur = dummyHead;
while (index--) {
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
ListNode* newNode = new ListNode(val); //创建新节点val
dummyHead->next = newNode;
len++;
}
void addAtTail(int val) {
ListNode* newNode = new ListNode(val);
ListNode* cur = dummyHead;
while (cur->next != nullptr) {
cur = cur->next;
}
cur->next = newNode;
len++;
}
void addAtIndex(int index, int val) {
if (index < 0) {
index = 0;
}
if (index > len) {
return;
}
ListNode* newNode = new ListNode(val);
ListNode* cur = dummyHead;
while (index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
len++;
}
void deleteAtIndex(int index) {
if (index < 0 || index > (len - 1)) {
return;
}
ListNode* cur = dummyHead;
while (index--) {
cur = cur->next;
}
cur->next = cur->next->next;
len--;
}
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
2.4 反转链表
双指针法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* temp; // 临时节点用于过渡
while (cur) {
temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
};