删除一个节点,我们首先要明确,这个要删除的节点有可能有多个,出现的位置可以是头节点,也可以不是头节点,同时如果链表就只有一个节点且是要删除的节点,那么该链表就成为了空链表
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语句,比较复杂
Comments NOTHING