理论基础
链表: 每个节点由两部分组成:数据域和指针域(存放指向下一个节点的指针);入口节点称为头节点;最后一个节点的指针域指向NULL(空指针)。
分类:
- 单链表
- 双链表:一个节点有两个指针域分别指向前一个节点及后一个节点。可以双向查询。
- 循环链表:头尾相连。
存储方式: 分散存储在内存空间中;
定义:
struct ListNode{int val;ListNode* next;ListNode(int x): val(x), next(nullptr){}
};
经典题目
虚拟头节点: ListNode* dummyhead = new ListNde(0);
链表头节点索引为 0;
无论是插入节点还是删除节点:cur指针必须指向被操作节点的前一个节点;
移除链表元素
- 定义虚拟头节点
dummyhead = head
; - 定义一个指针
cur = dummyhead
; - 在
cur->next != null
的情况下,遍历链表; - 判断
cur->next->val
是否等于val
; - 找到后,定义
temp
变量存储该节点,利用cur->next = cur->next->next
实现移除操作; - 释放被删除节点
temp
的内存。
设计链表
-
链表节点的定义及其初始化:
- 定义链表大小 _size = 0 ;
- 定义虚拟头节点 dummyhead;
-
链表最后插入一个节点
- 创建一个新节点 newNode;
- cur = dummyhead;
- 使cur移动到当前链表的最后一个节点:while(cur->next != NULL) cur = cur->next;
- cur->next = newNode;
- _size++;
-
获取链表中下标为 index 的节点的值
- 若 index 不在范围内,返回 -1;
- cur = dummyhead->next;
- 使cur移动到index节点处:while(index–),cur = cur->next;
- 循环结束,cur->val 即是 index节点的值;
-
在链表最前面插入一个节点
- 创建一个新节点 newNode;
- cur = dummyhead;
- newNode->next = cur->next;
- cur->next = newNode;
- _size++;
-
在第index节点前插入一个新节点;
- 若 index > _size,直接返回;若index < 0, index = 0;
- 创建一个新节点 newNode;
- cur = dummyhead;
- 使cur移动到第index节点前的一个节点处:while(cur->next != NULL) cur = cur->next;
- newNode->next = cur->next;
- cur->next = newNode;
- _size++;
反转链表
- 定义两个指针:pre = NULL; cur = head;
- 能实现反转的条件:cur != NULL
- 反转:
- 先保存 cur->next(后续会改变其指向):temp = cur->next;
- cur->next = pre;
- 移动:先移动pre = cur; 再移动cur = temp;
- 返回 pre;
两两交换链表中的节点
交换时,cur要指向交换的两个节点的前一个节点
- cur = dummyhead;
- 能实现交换的条件:cur->next != NULL && cur->next->next != NULL;
- 交换:
- 先保存会被改变的节点:temp = cur->next; temp1 = cur->next->next->next;
- cur->next = cur->next->next;
- cur->next->next = temp;
- temp->next = temp1;
- 移动:cur = cur->next->next;
删除链表中的倒数第index个节点
- 定义两个指针:fast 和 slow 都指向 dummyhead;
- fast先移动 index+1个节点;
- 当 fast != NULL 时,fast和 slow同时向后移动。
- 此时 slow 指向倒数第index个节点的前一个节点;利用 slow->next = slow->next->next删除节点;
链表相交
- 两个链表分别定义一个指针: curA = headA,curB = headB;
- 遍历两个链表分别求出其对应的长度:lenA 、lenB;
- 让curA和curB再次指向各自的头指针:curA = headA,curB = headB;
- 如果链表 A 的长度 大于 链表 B 的长度,对其长度和指针进行交换(swap函数),始终保持链表 A长度大于链表 B;
- 求出两者差值 gap,并将 curA向后移动 gap 个节点;
- 从 curA遍历两个链表,若 curA = curB,返回 curB(curA),(相交点),若没找到返回NULL。
判断是否成环
- 定义两个指针:fast = head,slow = head;
- 因为 fast每次走两个节点,slow每次走一个节点,因此循环判断条件是:fast != NULL && fast->next != NULL;
- 若 fast = slow,说明存在环
- 定义两个指针 index1 = head,index2 = slow;
- 当 index1 != index2时, index1 和index2 两个指针逐步向后移;
- 只要 index1 == index2 ,则 index1(index2)就是环的入口节点;若无环,返回NULL;