1.删除链表中等于给定值 val 的所有节点
思路:创建一个新的头结点和尾结点,创建一个pcur指向原链表的头结点进行遍历,当pcur->val不等于val的时候就让该结点尾插到新链表处;补充一点:创建新链表的时候如果链表为空则让新插入的结点称为头结点,这样子又要多一些判断,所以我们可以创建一个哨兵位,这样就保证新链表不为空且不需要判断;如下图和代码所示:
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val)
{
ListNode* pcur = head;
ListNode* Newhead = (ListNode*)malloc(sizeof(ListNode));
ListNode* Newtail = Newhead;
while(pcur)
{
if(pcur->val!=val)
{
Newtail->next = pcur;
Newtail = Newtail->next;
}
pcur = pcur->next;
}
if(Newtail)
{
Newtail->next = NULL;
}
ListNode* ret = Newhead->next;
free(Newhead);
return ret;
}
注意:在进行完while循环后,"5"就成了尾结点,那么还要让尾结点的next指针指向NULL,还要把Newhead释放掉,因为Newhead的空间是动态申请的防止内存泄漏;
2.反转一个单链表
思路:创建三个指针n1指向NULL、n2指向头结点、n3指向头结点的下一个节点;然后让n2->next指向NULL,n1走到n2的位置,n2走到n3的位置,当n3不为NULL的时候n3走到n3->next的位置,最后再返回n1,这样一直循环到n2为NULL的时候;这个操作是让结点的指向改变,并没有改变结点的位置;代码如下:
typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head)
{
if(head==NULL)
{
return head;
}
ListNode* n1 = NULL;
ListNode* n2 = head;
ListNode* n3 = n2->next;
while(n2)
{
n2->next = n1;
n1 = n2;
n2 = n3;
if(n3)
{
n3 = n3->next;
}
}
return n1;
}
3.链表的中间结点
思路:使用快慢指针,慢指针走一步,快指针走两步,后面要分两种情况,一种是结点总数为奇数的时候fast->next==NULL的时候停止,第二种是结点总数为偶数的时候则fast==NULL的时候停止,最后再返回慢指针;快慢指针原理:因为快指针每次都比慢指针快两步,所以假设快指针走了n步,那么慢指针就走了n/2步;代码如下:
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head)
{
ListNode* Fastp;
ListNode* Slowp;
Fastp = Slowp = head;
if(Fastp==NULL)
{
return Fastp;
}
while(Fastp&&Fastp->next)
{
Slowp = Slowp->next;
Fastp = Fastp->next->next;
}
return Slowp;
}
4.合并两个有序链表
思路:首先创建四个指针l1,l2,Newhead和Newtail,l1负责遍历第一个链表,l2负责遍历第二个链表,Newhead和Newtail负责新链表的头和尾;比较l1和l2,如果l1小于l2,那么就把l1放到新链表里面,如果l2小于l1就把l2放到新链表里面,合并两个链表中肯定有一个链表遍历不完,那么就把最后剩下的链表直接尾插到新链表即可,最后再返回新链表的头结点;如下代码所示:
typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
if(list1==NULL)return list2;
if(list2==NULL)return list1;
//创建新链表
ListNode* Newhead =NULL, *Newtail = NULL;
ListNode* L1 = list1;
ListNode* L2 = list2;
while(L1&&L2)
{
if(L1->val <L2->val)
{
if(Newhead==NULL)
{
Newhead = Newtail = L1;
}
else
{
Newtail->next = L1;
Newtail = Newtail->next;
}
L1 = L1->next;
}
else
{
if(Newhead==NULL)
{
Newhead = Newtail = L2;
}
else
{
Newtail->next = L2;
Newtail = Newtail->next;
}
L2 = L2->next;
}
}
if(L1)Newtail->next = L1;
if(L2)Newtail ->next = L2;
return Newhead;
}
END!