//思路一:遍历原链表,将值为val的节点释放,用三个指针存放
//千万注意:不能访问空指针的next
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
ListNode* prev,*pcur,*nex;
prev=head;
//这样写while循环才能保证把链表开头中全为val的节点弄掉
while(prev&&prev->val==val)//这两个条件的判断顺序不能变
{
// free(prev);//不能释放了空间再赋值
prev = prev -> next;
}
head=prev;
//判断去了开头的等于val的节点之后链表是否为空
if(prev)
{
pcur=head->next;
nex=pcur;
}
else
{
return head;
}
//链表不为空时去除中间的是val的节点
while(pcur)
{
if(pcur->val!=val)
{
pcur=pcur->next;
prev=prev->next;
nex=nex->next;
}
else
{
prev->next=nex->next;
pcur=nex->next;
// free(nex);
nex=pcur;
}
}
return head;
}
//注意:多个指针可以指向同一块空间,只需要改变指针指向就可以了
//思路二:创建新链表
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head,int val)
{
//创建一个空链表
ListNode* newHead,*newTail;
newHead=newTail=NULL;
//遍历原链表
ListNode* pcur=head;
while(pcur)
{
//找值不为val的节点,尾插到新链表中
if(pcur->val!=val)
{
if(newHead==NULL)//链表为空
{
newHead=newTail=pcur;
}
else//链表不为空
{
newTail->next=pcur;
newTail=newTail->next;//尾部指针不断后移
}
}
pcur=pcur->next;
}
if(newTail)//若初始链表不为空
newTail->next=NULL;
return newHead;//若初始链表为空直接返回也可以
};
//思路三:快慢指针
struct ListNode* removeElements(struct ListNode* head, int val)
{
//审题:val是一开始就定的数,而不是你想当然的数组下标!!!
//删除掉第一位的
while(head!=NULL && head->val==val){
head=head->next;
}
//第一位不会被删除的
struct ListNode* cur=head;
struct ListNode* s = NULL;
//错误代码示范:此句类型错误,while(cur!=NULL && head->val!=val){
while(cur!=NULL){
//快慢指针
s = cur->next;
while(s!=NULL && s->val == val){
cur->next = cur->next->next;
free(s);
s=cur->next;
}
cur = cur->next;
}
return head;
}
//思路四:递归
struct ListNode* removeElements(struct ListNode* head, int val){
if (NULL == head) {
return head;
}
/* 删除头节点后所有值为 val 的节点 */
struct ListNode* res = removeElements(head->next, val);
/* 头节点是待删除的节点 */
if (head->val == val) {
return res;
/* 头节点不是待删除的节点,头节点后面挂接已处理的链表(更短的) */
} else {
head->next = res;
return head;
}
}
//化简版:
struct ListNode* removeElements(struct ListNode* head, int val){
if (NULL == head) {
return head;
}
head->next = removeElements(head->next, val);
return head->val == val ? head->next : head;
}
//思路五:迭代
struct ListNode* removeElements(struct ListNode* head, int val){
while (NULL != head && head->val == val) {
head = head->next;
}
//链表中全是val的这种情况
if (NULL == head) {
return head;
}
struct ListNode* pre = head;
while (pre->next != NULL) {
/* 找到值为 val 的节点,并将其删除 */
if (pre->next->val == val) {
pre->next = pre->next->next;
} else {
/* 没找到,则继续遍历查找 */
pre = pre->next;
}
}
return head;
}
//思路六:虚拟头节点(哨兵)
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
if (NULL == dummyHead) {
return NULL;
}
dummyHead->next = head;
struct ListNode* cur = dummyHead;
while (cur->next != NULL) {
if (cur->next->val == val) {
ListNode* delNode = cur->next;//这个地方注意要创建一个新指针
cur->next = delNode->next;
free(delNode);
} else {
cur = cur->next;
}
}
//注意返回的是第一个真正的节点,而不是虚拟节点
struct ListNode* retNode = dummyHead->next;
free(dummyHead);
return retNode;
}