1.移除链表元素
LeetCode链接: 【203. 移除链表元素】
这个题目和单链表的增删查改接口很相似,要我们删除链表中的元素。要注意题目给我们的是无头单向不循环链表,是没有哨兵位结点的,所以删除的元素有两种情况:
1.可能在链表的头结点
2.可能在链表的其它结点位置
而头结点的删除和在其它结点删除是不一样的,头结点删除就让下一个结点当头结点就可以了;其它结点删除要找到前一个结点和后一个结点,然后把前结点和后结点链接起来就可以了。
所以针对以上分析,我们有两种解决方法:
1.直接在原来链表上进行删除,不过当找到要删除的元素时,每一次都要判断该结点是头结点还是其它结点;
2.构造一个哨兵位结点,把链表的头结点链接在哨兵位结点后面,这样当找到要删除的元素时就都是在链表的其它结点删除了,这样避免要分两种情况去讨论。
方法1:不构造哨兵位
//移除链表元素
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* cur=head;
struct ListNode* next=NULL;
struct ListNode* prev=NULL;
struct ListNode* newHead=head;
while(cur!=NULL)
{
//等于val有2种情况
//1.头节点为val
if(cur->val==val)
{
if(cur==head)
{
newHead=cur->next;
free(cur);
cur=newHead;
head=newHead;
}
//2.其它节点为val
else
{
next=cur->next;
free(cur);
prev->next=next;
cur=next;
}
}
//不等于val就迭代往后走
else
{
prev=cur;
next=cur->next;
cur=next;
}
}
return newHead;
}
方法2:构造哨兵位
struct ListNode* removeElements(struct ListNode* head, int val){
//开辟一个哨兵位结点,哨兵结点的指针域存放链表的头指针
struct ListNode* newHead=
( struct ListNode*)malloc(sizeof( struct ListNode));
newHead->next=head;
struct ListNode* prev=newHead;
struct ListNode* cur=newHead->next;
struct ListNode* next=NULL;
while(cur!=NULL)
{
//等于val就删除改结点,并把前后结点链接起来
if(cur->val==val)
{
next=cur->next;
free(cur);
prev->next=next;
cur=next;
}
//不等于val就找下一个
else
{
prev=cur;
next=cur->next;
cur=next;
}
}
//释放哨兵位结点,返回哨兵位结点的指针域即(链表的头结点)
struct ListNode* tmp=newHead->next;
free(newHead);
return tmp;
}
2.反转链表
LeetCode链接: 【206. 反转链表】
要求反转链表本质上就是把结点的指针域内容给改变,从原来结点存放下一个结点的地址改成结点存放上一个结点的地址。
我们可以用【头插法】来搞定,不断地取链表的头结点来头插,取到链表没有结点为止。
过程分析如下:
代码实现如下:
struct ListNode* reverseList(struct ListNode* head){
if(head==NULL)
{
return head;
}
struct ListNode* prev =NULL;
struct ListNode* cur=head;
while(cur!=NULL)
{
struct ListNode* next=cur->next;
//让该结点指针域存放上一个结点的地址
cur->next=prev;
//迭代过程
prev=cur;
cur=next;
}
return prev;
}