c++链表删除指定元素

给定N个整数,将这些整数中与M相等的删除
假定给出的整数序列为:1,3,3,0,-3,5,6,8,3,10,22,-1,3,5,11,20,100,3,9,3
应该将其放在一个链表中,链表长度为20
要删除的数是3,删除以后,链表中只剩14个元素:1 0 -3 5 6 8 10 22 -1 5 11 20 100 9

要求:必须使用链表,不允许使用数组,也不允许不删除元素直接输出
程序中必须有链表的相关操作:建立链表,删除元素,输出删除后链表中元素,释放链表。
不符合要求的程序即使通过,也会算作0分


#include<bits/stdc++.h>
using namespace std;
struct Node
{
    int data;
    Node *next;
};
Node *head,*p,*r;
int x;
int main()
{
    int n,m,i;
    head=new Node;
    r=head;
    cin>>n;
    i=n;
    while(i>0)
    {
        cin>>x;
        p=new Node;
        p->data=x;
        p->next=NULL;
        r->next=p;
        r=p;
        i--; 
    }
    cin>>m;
    p=head->next;
    do
    {
        if(p->next->data==m)
        {
            Node *s;
            s=p->next;
            p->next=p->next->next;
            free(s);    
        }
        p=p->next;
    }while(p->next!=NULL);
    p=head->next;
    do
    {
        cout<<p->data<<" ";
        p=p->next;
    }while(p->next!=NULL);
    return 0;
}

没法子输出。

输出应该还是有的吧,只不过有些错误,已在注释中写明,望采纳

do
    {
        if(p->next->data==m)//直接判断p->next,没有判断p->data,可以在前面改为p=head
        {
            Node *s;
            s=p->next;
            p->next=p->next->next;
            free(s);    //这应该用delete,并且直接continue,不能执行p=p->next,否则两个连续目标值就会漏掉
        }
        p=p->next;
    }while(p->next!=NULL);
    p=head->next;

还有一处错误,下面这段代码应该用while而不是do..while,或者将判断语句改为p!=NULL,否则无法输出最后一个元素

do
    {
        cout<<p->data<<" ";
        p=p->next;
    }while(p->next!=NULL);

删除时:if(p->next->data==m) 跳过了元素,应该用p->data,用另一个指针(如:t)表示p的前一个元素,t->next=p->next; free(p);
输出时:循环中 p=p->next; 此后p可能为NULL,然后 while(p->next!=NULL); 会遇到空指针。用while(p!=NULL) {},用原循环体内容

代码块如下:
1.链表节点

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

2.链表类

class LinkedList {
private:
    Node* head;
    
public:
    LinkedList() : head(nullptr) {}
    
    // 在链表头部插入节点
    void prepend(int value) {
        Node* newNode = new Node(value);
        newNode->next = head;
        head = newNode;
    }
    
    // 删除与给定数相等的节点
    void remove(int value) {
        Node* current = head;
        Node* prev = nullptr;
        
        while (current != nullptr) {
            if (current->data == value) {
                if (prev == nullptr) {
                    // 删除头节点
                    head = current->next;
                    delete current;
                    current = head;
                } else {
                    prev->next = current->next;
                    delete current;
                    current = prev->next;
                }
            } else {
                prev = current;
                current = current->next;
            }
        }
    }
    
    // 输出链表中的元素
    void print() {
        Node* current = head;
        while (current != nullptr) {
            std::cout << current->data << " ";
            current = current->next;
        }
        std::cout << std::endl;
    }
    
    // 释放链表内存
    void release() {
        Node* current = head;
        while (current != nullptr) {
            Node* temp = current;
            current = current->next;
            delete temp;
        }
        head = nullptr;
    }
};

3.主函数:

int main() {
    int arr[] = {9,3,100,20,11,5,3,9,3,22,10,3,8,6,5,-3,0,3,3,1};
    int size = sizeof(arr) / sizeof(arr[0]);
    int removeValue = 3;
    
    LinkedList myList;
    
    // 将整数序列插入链表
    for (int i = size - 1; i >= 0; i--) {
        myList.prepend(arr[i]);
    }
    
    std::cout << "原始链表: ";
    myList.print();
    
    // 删除与给定数相等的节点
    myList.remove(removeValue);
    
    std::cout << "删除" << removeValue << "后的链表: ";
    myList.print();
    
    // 释放链表内存
    myList.release();
    
    return 0;
}

已做注释,希望能帮到你,加油~~~

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7754964
  • 除此之外, 这篇博客: 回溯法与分支限界法的总结中的 在当前节点(扩展节点)处,先生成其所有的子节点(分支),然后再从当前的活节点(当前节点的子节点)表中选择下一个扩展节点。为了有效地选择下一个扩展节点,加速搜索的进程,在每一个活节点处,计算一个函数值(限界),并根据函数值,从当前活节点表中选择一个最有利的节点作为扩展节点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解。分支限界法解决了大量离散最优化的问题。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    编写回溯算法代码时,要先考虑这个问题是一个什么搜索树,然后套用那个搜索树模板就行了。(例如:子集树就是:判断是否满足约束条件——计算、x[i]=1——递归左子树——归还——x[i]=0、递归右子树(注意限界思想))
    (例如:排列树就是:循环——判断是否满足约束条件——交换——计算——递归(注意限界思想)——归还)
    当然具体算法要具体分析
    还要注意及时更新解和存储解,别忘了进入右子树、循环结束前,要将你算的、交换过的东西,要归还回去。注意到达叶结点干什么,没有到达怎么做

    而分支限界算法的代码编写,首先编写三个类:活结点类、活结点属性类、入队类。然后选择好什么样的队列方式。一定要考虑好属性,然后什么时候添加结点、以及出队、和存储最优解

    两个算法编写,还要注意限界函数的设置,怎么设计一个好的代价函数可以裁掉更多的空间。这就是两个算法的优化思想。

    当然最重要的还要考虑好约束条件。

    具体逻辑代码还是多写多练。多去总结。这里也就只讲个大体思路。

  • 以下回答来自chatgpt:
    #include <iostream>
    using namespace std;
    
    struct Node {
        int value;
        Node* next;
    };
    
    Node* createLinkedList(int arr[], int len) {
        Node dummyHead, * cur;
        cur = &dummyHead; // 定义一条虚拟头结点,当做 Head 指针使用
        for (int i = 0; i < len; i++) {
            Node* newNode = new Node{arr[i], NULL};
            cur->next = newNode;
            cur = cur->next;
        }
        return dummyHead.next;
    }
    
    void deleteNode(Node* head, int target) {
        Node dummyHead{0, head}, * cur;
        cur = &dummyHead;
        while (cur->next) {
            if (cur->next->value == target) {
                Node* temp = cur->next;
                cur->next = cur->next->next;
                delete temp;
            } else {
                cur = cur->next;
            }
        }
    }
    
    void printLinkedList(Node* head) {
        while (head) {
            cout << head->value << " ";
            head = head->next;
        }
        cout << endl;
    }
    
    void freeLinkedList(Node* head) {
        while (head) {
            Node* temp = head;
            head = head->next;
            delete temp;
        }
    }
    
    int main() {
        int arr[] = {1, 2, 3, 3, 4, 3, 5, 3};
        int len = sizeof(arr) / sizeof(int);
        Node* head = createLinkedList(arr, len);
        cout << "Before delete: ";
        printLinkedList(head);
        deleteNode(head, 3);
        cout << "After delete: ";
        printLinkedList(head);
        freeLinkedList(head);
        return 0;
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^