【C++】删除单链表中特定值的节点

介绍

在编程中,处理链表是一个基本的技能,本位主要介绍如何删除特定的节点。这是一个非常常见的操作。

问题陈述

给定一个单链表,我们需要实现一个函数,该函数接受一个值作为输入,并在链表中删除具有该值的所有节点。最终,我们将返回修改后的链表。

解决方案

我们将通过遍历链表来找到并删除目标值的节点。具体来说,我们将保持两个指针:一个用于当前节点,另一个用于追踪前一个节点。当我们找到目标值时,我们将通过修改前一个节点的next指针来删除当前节点。

算法

  1. 初始化一个指向头节点的指针current和一个指向前一个节点的指针prev,并将它们都指向头节点。
  2. 遍历链表,直到当前节点为空。
  3. 如果当前节点的值等于目标值,则:
  • 将前一个节点的next指针指向当前节点的下一个节点。
  • 释放当前节点的内存。
  • 将当前节点指针移动到下一个节点。
  1. 否则,更新prev指针为当前节点,将当前节点指针移动到下一个节点。
  2. 返回修改后的链表。

代码实现

#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* next;
    Node(int val) : data(val), next(nullptr) {}
};

class LinkedList {
private:
    Node* head;

public:
    LinkedList() : head(nullptr) {}

    void append(int val) {
        if (!head) {
            head = new Node(val);
            return;
        }
        Node* temp = head;
        while (temp->next) {
            temp = temp->next;
        }
        temp->next = new Node(val);
    }

    void deleteNode(int key) {
        Node* current = head;
        Node* prev = nullptr;

        while (current) {
            if (current->data == key) {
                if (prev)
                    prev->next = current->next;
                else
                    head = current->next;
                
                Node* temp = current;
                current = current->next;
                delete temp;
            } else {
                prev = current;
                current = current->next;
            }
        }
    }

    void display() {
        Node* temp = head;
        while (temp) {
            cout << temp->data << " ";
            temp = temp->next;
        }
        cout << endl;
    }
};

int main() {
    LinkedList linkedList;
    linkedList.append(1);
    linkedList.append(2);
    linkedList.append(3);
    linkedList.append(4);

    cout << "原始链表:" << endl;
    linkedList.display();

    linkedList.deleteNode(3);

    cout << "删除节点后的链表:" << endl;
    linkedList.display();

    return 0;
}

示例与测试

int main() {
    LinkedList linkedList;
    linkedList.append(1);
    linkedList.append(2);
    linkedList.append(3);
    linkedList.append(4);

    cout << "原始链表:" << std::endl;
    linkedList.display();

    linkedList.deleteNode(3);

    cout << "删除节点后的链表:" << std::endl;
    linkedList.display();

    return 0;
}

注意点**

deleteNode()函数中有这么一串负责删除的代码:

            if (current->data == key) {
                if (prev)
                    prev->next = current->next;
                else
                    head = current->next;
                
                Node* temp = current;
                current = current->next;
                delete temp;
            }

删除之前为什么要进行 i f ( p r e v ) if(prev) if(prev)的判定呢,这是因为在删除单链表中的节点时,我们需要考虑两种情况:

  1. 如果要删除的节点是头节点。
  2. 如果要删除的节点不是头节点。

当要删除的节点是头节点时,我们需要更新链表的头指针,使其指向被删除节点的下一个节点。而如果要删除的节点不是头节点,我们需要将前一个节点的next指针指向被删除节点的下一个节点,以确保链表仍然保持连续性。

因此,在代码中的if (prev)判定的目的是检查是否存在前一个节点。如果前一个节点存在,我们可以安全地更新前一个节点的next指针,以删除当前节点。如果前一个节点不存在(即当前节点是头节点),我们需要特别处理,将链表的头指针指向当前节点的下一个节点。

其他写法对比

版本一:

void Delete LinkList(LNode * L,int key) 
{
	//删除以L为头结点的单链表中值为key的第一个节点
	LNode *p=L,*q=L->next;
	while(q!=NULL&&q->data!=key){p=q;q=q->next;}
	if(q->data==key){p->next=q->next;free();}
	else printf("NULL\n");
}

版本二:

	while(p->next!=NULL&&p->next->data!=key){p=p->next;}
	if(p->next->data==key)
	{
		q=p->next;
		p->next=q->next;
		free();
	}

这两个版本的区别是版本一是判断当前节点是否为空以及是否为目标值,而版本二则是针对下一个节点进行判断,版本一的好处就是能够保证最后停留的节点不是NULL,然后在进行是否是目标节点的判断,但是版本二无法保证最后停止的节点是否为NULL,所以上面的写法是错误的,需要在if语句前面加上一个是否是NULL的判断,否则p==NULL的情况下进行p->next->data操作会出现bug。

C++单链表是一种常见的数据结构,其每个节点包含一个数据元素和对下一个节点的引用。删除一个节点通常涉及指针操作,特别是当你需要删除某个特定节点或者头部节点时。这里是一个简单的例子,展示了如何删除给定节点: ```cpp #include <iostream> // 定义链表节点 struct Node { int data; Node* next; // 指向下一个节点的指针 }; // 删除给定节点函数 Node* deleteNode(Node*& head, int value) { if (head == nullptr) { // 如果链表为空,直接返回 return nullptr; } Node* temp = head; // 初始化临时指针 if (temp->data == value) { // 首部节点匹配,更新头节点 head = temp->next; delete temp; // 释放旧节点内存 return head; } while (temp != nullptr && temp->data != value) { // 查找目标节点 temp = temp->next; } if (temp == nullptr) { // 找不到目标节点,未删除 std::cout << "Value not found in the list.\n"; return head; } // 跳过找到的目标节点,然后更新其前一个节点指向下一个节点 temp->prev->next = temp->next; if (temp->next != nullptr) { // 如果不是尾节点,释放节点内存 delete temp; } else { // 如果是尾节点,只删除这个节点 delete temp->prev; } return head; } int main() { // 创建链表示例并删除指定 Node* head = new Node{5, new Node{7, new Node{2, new Node{9, nullptr}}}}; deleteNode(head, 7); // 删除为7的节点 // ... 这里可以添加查看修改后的链表的操作 return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要AC的dly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值