12.5 删除链表中的某个节点(含循环链表)

发布于 2024-12-05  97 次阅读


删除一个节点,我们首先要明确,这个要删除的节点有可能有多个,出现的位置可以是头节点,也可以不是头节点,同时如果链表就只有一个节点且是要删除的节点,那么该链表就成为了空链表

void delete(int data, node** head) {
	if (*head == NULL) {
		return;
	}
	node* cur = *head;
	node* pre = NULL;
	while (cur != NULL) {
		if (cur->data == data) {
			if (cur == *head) {
				*head = cur->next;
				free(cur);
				cur = *head;
			}
			else {
				pre->next = cur->next;
				free(cur);
				cur = pre->next;
			}
		}
		else {
			pre = cur;
			cur = cur->next;
		}
	}
}

第一点,由于如果头节点也是需要删除的节点,我们需要将原来的第二个节点改成头节点,但是如果链表只有一个节点,那么将"head"=NULL即可

if (cur == NULL) {
	if(cur->next==NULL){
          *head=NULL;
           free(cur);
        }else{
          *head = cur->next;//可能有这一步,所以必须传参&head
	  free(cur);
	  cur = *head;
        }
}

//第二点(不咋important),如果*head本身就是NULL,代表这个链表就是个空链表,所以啥也不用干直接返回,可以写在delete函数的最前面

if (*head == NULL) {
	return;
}

cur表示当前节点,我们初始化为头节点

pre表示cur的前一节点,我们初始化为NULL

node* cur = *head;
node* pre = NULL;

我们需要查找链表的全部节点,所以建立一个简单的循环

while (cur != NULL) {
   //做很多事,其中肯定包括更新cur为下一节点
  //所以如果cur==NULL,就表示我们已经遍历完全部节点
}

在这个循环里面,我们需要找到匹配的节点并进行删除操作

if (cur->data == data) {
	if (pre == NULL) {
		*head = cur->next;
		free(cur);
		cur = *head;
	}
	else {
		pre->next = cur->next;
		free(cur);
		cur = pre->next;
	}
}else {
	pre = cur;
	cur = cur->next;
}

这里也是核心代码,分两种情况:

1.此时遍历的节点就是要删除的节点,里面又包括该节点是头节点和不是头节点两种情况

if (cur->data == data) {
	if (pre == NULL) {
	//pre是空,说明pre还是初始化的值,要删除的节点就是头节点
                *head = cur->next;//直接"head"更新为下一个节点
                //这里pre就不需要更新了,反正头节点也没有pre,本来就是空
                free(cur)//释放cur的内存
                cur=*head//更新cur为新的头节点
	}
	else {
	      pre->next = cur->next;//更新前节点pre
	      free(cur);//释放cur的内存
	      cur = pre->next;//更新cur为pre的新的下一节点,也是原来的cur的下一节点
	}
}

2.此时遍历的节点不是要删除的节点,直接进行pre和cur的更新

else{
              pre = cur; // 更新前节点pre
              cur = cur->next; // 更新cur为下一个节点
}

//PS:free掉cur的内存是执行“删除”操作,cur= sth 是更新cur为新的节点,实现下一节点的遍历


单循环链表需要建立三个if-else语句,比较复杂

届ける言葉を今は育ててる
最后更新于 2024-12-24