本篇文章分享几个关于单链表的操作: 1.删除链表的节点
2.链表中倒数第k个节点
3.反转链表
4.合并两个有序链表
1.删除链表的节点
//删除链表的节点
//这里运用双指针,需要获得前驱节点
class Solution {
public:
//双指针,获取前驱
ListNode* deleteNode(ListNode* head, int val) {
if(head.val==val)//如果头节点就是val值,那么直接返回从头节点的下一个节点为开始的链表
return head.next;
ListNode* pre=head;//左指针从头节点开始
ListNode* cur=head.next;//右指针从头节点的下一个节点开始
for(;cur!=NULL;cur=cur->next)//循环找到目标节点的前驱节点
{
if(cur->val==val)//如果找到了,那么目标节点cur的前驱节点就是pre
{
pre->next=cur->next;//把目标节点的下一个节点赋值给前驱节点的下一个节点
//从而实现删除目标节点
break;//删除后直接退出循环
}
pre=cur;//若没找到 pre、cur往下走一个节点 继续找 直到cur==NULL进不去循环为止
}
return head;//返回以head为头节点的链表
}
};
2.链表中倒数第k个节点
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
//双指针
if(head==NULL||k==0)//若头节点值为空或者k=0,则直接返回null
return NULL;
ListNode* pre=head;//定义两个指针,都从头节点位置开始
ListNode* cur=head;
//先把cur指针移动到正数k的位置,
//从而使pre和cur永远相差k个位置,那么当cur=null时,pre此时的位置就是倒数第k个节点
//所以循环结束条件为k,同时cur不能为空
while(k>0&&cur!=NULL)
{
cur=cur->next;//cur往后移一位
k--;
}
//判断cur是否为null
//如果是,那么说明倒数第k个节点就是头节点,直接返回头节点head
//eg.1->2->3 k=3
if(cur==NULL)
return head;
//不是上面这种特殊情况
//两个指针同时向后移动,当cur移动到链表最后一个节点时,循环结束
while(cur!=NULL)
{
pre=pre->next;
cur=cur->next;
}
//此时pre的位置就是倒数第k个节点的位置
return pre;
//如果不用双指针的方法,那么就先遍历一遍链表,找到链表长度n,再遍历链表,使指针p移动到n-k的位置,此时p所在的位置即为倒数第k个节点
}
};
3.反转链表
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//迭代(双指针)
if(head==NULL||head->next==NULL)
return head;
//定义两个指针
ListNode* pre=NULL;
ListNode* cur=head;
while(cur!=NULL)
{
ListNode* tmp=cur->next;//保存后继节点
cur->next=pre;//修改引用指向(将当前节点的后继节点指向它的前驱节点)
pre=cur;//更新前驱节点
cur=tmp;//访问下一节点
}
}
};
4.合并两个有序链表
//本题用了两种解法,分别是递归和迭代两种解法
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
//递归解法
if(l1==NULL)//如果l1为空,直接返回l2
return l2;
else if(l2==NULL)//反之,同理
return l1;
//如果两个链表任意一个为空,那么递归结束
else if(l1->val<l2->val)//如果l1链表的头节点的值小于l2链表头节点的值
{
//将l1->next和l2链表进行排序
l1->next=mergeTwoLists(l1->next,l2);
return l1;
}
//如果l2链表的头节点的值小于l1链表头节点的值
else
{
//将l1和l2->next开始的链表进行排序
l2->next=mergeTwoLists(l1,l2->next);
return l2;
}
//迭代解法
ListNode* resHead=new ListNode(-1);//定义一个新链表,用来存放结果
ListNode* pre=resHead;//pre指针从新链表的头节点开始
while(l1!=NULL&&l2!=NULL)//两个链表不能同时为空
{
if(l1->val<l2->val)//如果链表1当前节点的值小于链表2的
{
pre->next=l1;//给新链表里插入当前节点
l1=l1->next;//同时将链表1的指针后移一位
}
else//反之
{
pre->next=l2;//给新链表里插入当前节点
l2=l2->next;//同时将链表2的指针后移一位
}
//注意:要调整pre的next,这样下次链接下一个元素的位置才是正确的
pre=pre->next;
}
//循环结束后,l1和l2只有一个链表为空
//将剩下的非空链表链接到pre的后面
pre->next=l1==NULL?l2:l1;
//返回结果链表中头节点的下一个节点
//因为头节点初始化为-1,我们不需要打印这个值
return resHead->next;
}
};