206.反转单链表
方法一:头插(最简单)
将原链表元素依次取下,进行头插
truct ListNode* reverseList(struct ListNode* head)
{
struct ListNode*newhead=NULL;
struct ListNode*cur=head;
while(cur)
{
struct ListNode*next=cur->next;
//头插
cur->next=newhead;
newhead=cur;
cur=next;
}
return newhead;
}
方法二 改变指针方向
定义三个指针
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
//单独处理空链表
if(head==NULL)
return head;
struct ListNode*n1,*n2,*n3;
n1=NULL;
n2=head;
n3=n2->next;
while(n2)
{
//反转指向
n2->next=n1;
//迭代
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
}
这个还可以用递归来做,但是链表过长时,程序容易崩溃。不建议用
201.移除链表元素
方法一:遍历+删除
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode*prev=NULL;
struct ListNode*cur=head;
while(cur)
{
if(cur->val==val)
{
if(cur==head)
{
//头删(要更新头节点)
head=cur->next;
free(cur);
cur=head;
}
else
{
//删除
prev->next=cur->next;
free(cur);
cur=prev->next;
}
}
else
{
prev=cur;
cur=cur->next;
}
}
return head;
}
方法二 遍历+尾插(用一个tail指针记下尾,方便多次尾插)
遍历,找到不等于val的值进行尾插
注意事项
1.结束时要处理尾节点
if(tail) tail->next=NULL;
否则会出现下面的问题
2.开头head=NULL
否则
正确的完整代码
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode*cur,*tail;
cur=head;
tail=NULL;
head=NULL;
while(cur)
{
if(cur->val==val)
{
//删除
struct ListNode*del=cur;
cur=cur->next;
free(del);
}
else
{
//尾插
if(tail==NULL)
{
head=tail=cur;
}
else
{
tail->next=cur;
tail=tail->next;
}
cur=cur->next;
}
}
if(tail)
tail->next=NULL;
return head;
}
方法三 :
方法三是在二的基础上添加了一个带哨兵位的头节点,可以规避掉注意实现1,2.
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode*cur=head;
struct ListNode*tail=NULL;
//哨兵位的头节点
head=tail=(struct ListNode*)malloc(sizeof(struct ListNode));
tail->next=NULL;
while(cur)
{
if(cur->val==val)
{
//删除
struct ListNode*del=cur;
cur=cur->next;
free(del);
}
else
{
//尾插
tail->next=cur;
tail=tail->next;
cur=cur->next;
}
}
tail->next=NULL;
//释放掉哨兵位头节点
struct ListNode*del=head;
head=head->next;
free(del);
return head;
}
876.链表的中间节点
----快慢指针的简单应用
struct ListNode* middleNode(struct ListNode* head){
assert(head);
//快慢指针
//每次快指针比慢指针多走一步
struct ListNode*fast=head;
struct ListNode*slow=head;
while(fast!=NULL&& fast->next != NULL)
{
fast=fast->next->next;
slow=slow->next;
}
return slow;
}