1.链表基础知识:
- 链表分类:单链表、双链表、循环链表
- 链表的存储:散乱分布,通过指针域的指针链接在一起
- 链表的定义:此处给出单链表的c++定义
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {
} // 节点的构造函数
};
- 链表初始化及调用:
ListNode* head = new ListNode(5); //使用上述定义中的构造函数来初始化
ListNode* head = new ListNode(); //使用c++默认构造函数来初始化
head -> val = 5;
int a = head -> val; //调用的方式
ListNode* temp = head; //head其实是链表的首地址,有了首地址就有了整个链表
temp = head -> next;
- 链表的操作:删除节点、增加节点
- 性能分析
链表的查询都是要从头节点开始遍历的,所以时间复杂度是O(n),但是空间复杂度较低,一般都是O(1)
2.典型题
2.1删除节点
leetcode地址:https://leetcode-cn.com/problems/remove-linked-list-elements/
2.1.1 直接删除
直接用原链表进行删除操作(在删除头节点时需要一段单独的逻辑去判断和操作),注意在c++中内存是要自己释放的,用delete关键字。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//删除头节点
while((head != NULL)&&(head->val == val)){
//不是空链表且头节点的值与目标值相等
ListNode* temp = head;
head = head->next;
delete temp;
}
//删除非头节点
ListNode* cur = head; //头节点不动,
while((cur != NULL)&&(cur->next != NULL)){
//不是空链表且不是尾部节点
if(cur->next->val == val){
//如果下一个节点的值等于目标值,跳过,且删除
ListNode* temp = cur->next; //
cur->next = cur->next->next;
delete temp;
}
else{
cur = cur->next;
}
}
return head;
}
};
2.1.2 虚拟头节点
设置一个虚拟头节点再进行删除操作。
class Solution {
//虚拟头节点的方法
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummynode = new ListNode(0); //新建一个链表,虚拟头节点
dummynode->next = head;
ListNode* cur = dummynode; //
while(cur->next != NULL){
if(cur->next->val == val)