数据结构修炼:链表习题讲解!!!
题一:移除链表元素
我们可以看出这道题是让我们删除特定数据,我们可以用双指针来解这道题:
如果首元素为val,那么cur和head一起后移:
如果没有碰到val,那么就会cur后移,并且提前将cur传给perv:
如若不是在首位碰到了val ,那么perv的下一个节点将会被覆值为cur的下一个节点,然后cur
将被继续赋值为perv的下一个节点,再返回原来的head头地址!!!
如图:
代码:
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* cut = head, * pevr = NULL;while (cut){if (cut->val == val){if (cut == head){head = cut->next;cut = head;}else{pevr->next = cut->next;cut =pevr->next;}}else{pevr = cut;cut = cut->next;}}return head;
}
题目二:
中间节点
我们有一个处理链表的重要思路:快慢指针,我们可以先定义快指针的速度是慢指针的两倍,然后我们在设置一个结尾的条件即可
图示思路:
这时候返回slow即可
当节点的数目为偶数的时候
如图所示:
当快指针指向NULL时,结束循环!!!
此时会指向中间第二节点,题目得解
代码:
struct ListNode* reverseList(struct ListNode* head){struct ListNode* p = head;struct ListNode* q = NULL;while(p){struct ListNode* temp = p->next;p->next = q;q = p;p = temp;}return q;
}
题目三:反转链表
这道题乐言使用的是三指针,直接断链再连上
我们首先定义一个结构体指针p指向head,再定义一个结构体指针指向空,链表的节点不变,我们进入循环while(),括号里放p的值,然后再定义一个结构体指针tmp指向p的下一个节点,这样我们可以得到我们想得到的循环次数
进入循环,我们让p的下一个节点指向q(也就是刚刚定义的空指针)
再将p的值赋值为q,再将p转移回原来的下一个节点,也就是tmp
这样操作的话,我们逐句带入的话,q的值会从NULL到1->NULL到2->1->NULL............然后最后实现链表的反置!!!
代码如下:
struct ListNode* reverseList(struct ListNode* head){struct ListNode* p = head;struct ListNode* q = NULL;while(p){struct ListNode* temp = p->next;p->next = q;q = p;p = temp;}return q;
}
题目四:合并两个有序链表
我们首先先初始化一个指针p,再初始化一个指向空指针的指针pp,然后进入循环,比较链表的首节点的元素大小进行比较,哪个小就指向哪个,然后再进行比较,循环往复
代码如下:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{struct ListNode *p = NULL, **pp = &p;while (list1 && list2){if (list1->val < list2->val){*pp = list1;list1 = list1->next;}else{*pp = list2;list2 = list2->next;}pp = &(*pp)->next;}*pp = list1 ? list1 : list2;return p;
}
希望此篇可以帮助到大家