c++ 我创建了一个LinkedList,并且正在尝试删除该元素,它只删除该元素一次,而不是与之匹配的所有元素

exdqitrt  于 2023-01-15  发布在  其他
关注(0)|答案(3)|浏览(99)
#include <iostream>
using namespace std; 

class Node {
    public :
        int val;
        Node* next;

        Node(int data) {
            this -> val = data;
            this -> next = NULL;
        }
};

void insertAtTail(Node* &tail, int data) {
    Node* temp = new Node(data);
    tail -> next = temp;
    tail = temp;
}

void print (Node* head) {
    while(head != NULL) {
        cout << head -> val << " ";
        head = head -> next;
    }
    cout << endl;
}

Node* removeElement(Node* head, int val) {
    if(head -> val == val) {
        while(head -> val == val) {
            head = head -> next;
        }
        return head;
    }

    else {
        Node* prev = NULL;
        Node* curr = head;
        while(curr -> next != NULL) {
            prev = curr;
            curr = curr -> next;
            if(curr -> val == val) {
                prev -> next = curr -> next;
            }
            //cout << prev -> val << " ";  
        }
        
    return head;
    }
}
int main () {
    Node* node1 = new Node(1);
    Node* head = node1;
    Node* tail = node1;

    insertAtTail(tail, 1);
    insertAtTail(tail, 1);
    insertAtTail(tail, 3);
    insertAtTail(tail, 3);
    insertAtTail(tail, 5);
    
    print(removeElement(head, 3));
}

1.问题-
在这个例子中,我在linkedlist中传递了元素到tail,然后我尝试使用**removeElement()**删除specific元素,它只删除一个匹配的元素,并留下其他匹配的元素
Image
我想删除所有与之匹配的元素。

3qpi33ja

3qpi33ja1#

什么都比不上画画。
你应该用笔和纸,但这里有一个ASCII版本的你正在做的事情:

p is null
 
head->1->1->3->3->5
 ^
 c

prev = curr;

 p
 v
head->1->1->3->3->5
 ^
 c

curr = curr->next

 p
 v
head->1->1->3->3->5
      ^
      c

prev = curr;

      p
      v
head->1->1->3->3->5
      ^
      c

curr = curr->next

      p
      v
head->1->1->3->3->5
         ^
         c

prev = curr;

         p
         v
head->1->1->3->3->5
         ^
         c

curr = curr->next

         p
         v
head->1->1->3->3->5
            ^
            c

if(curr -> val == val) {
    prev -> next = curr -> next;
}

         p +----+
         v |    v
head->1->1-+ 3->3->5
             ^
             c 

(Note that this detaches 'curr' from the list.)             

prev = curr;

           +----+
           |    v
head->1->1-+ 3->3->5
             ^
             c
             p

(And 'prev' now points to the detached node.)

curr = curr->next

           +----+
           |    v
head->1->1-+ 3->3->5
             ^  ^
             p  c


if(curr -> val == val) {
    prev -> next = curr -> next;
}

           +-------+
           |       v
head->1->1-+ 3-+   3->5
             ^ |   ^  ^
             p |   c  |
               |      |
               +------+

(And this sets the 'next' pointer of a node that is no longer part of the list.)

prev = curr;

           +-------+
           |       v
head->1->1-+ 3-+   3->5
               |   ^  ^
               |   c  |
               |   p  |
               +------+

curr = curr->next

           +-------+  c
           |       v  v
head->1->1-+ 3-+   3->5
               |   ^  ^
               |   p  |
               |      |
               +------+

and curr->next is null.

Result:

           +-------+   
           |       v   
head->1->1-+       3->5

现在用笔和纸计算出代码应该做什么,然后将其转换为代码。
(Hint:根据是否删除节点,您需要执行不同的操作。)

busg9geu

busg9geu2#

这个实现有一些问题,在很多测试用例中都不起作用。但是,在removeElement的第二个while循环中至少有一个主要问题。我尝试通过对您发送的特定测试进行最小修改来解决它。
将其替换为以下代码:

while(curr -> next != NULL) {
  if(curr -> val == val) {
    prev -> next = curr -> next;
    curr = prev -> next;
  }
  else {
    prev = curr;
    curr = curr -> next;
  }
  //cout << prev -> val << " ";  
}
wnrlj8wa

wnrlj8wa3#

你应该如何处理这个问题取决于你写代码的真正目的。如果你打算把它投入实际使用,你可能不想写任何东西。标准库已经有了链表的代码,如果没有其他原因,你通常会想使用它。

// intersperse '1' with other elements:
    std::forward_list<int> ints { 1, 3, 1, 3, 1, 5, 1 };

    // remove all the '1' elements:
    ints.remove(1);

    // print out the result:
    std::copy(ints.begin(), ints.end(),
        std::ostream_iterator<int>(std::cout, " "));

结果:

3 3 5

没有混乱,没有大惊小怪,没有内存泄漏。更好的是,这是相当容易转换为(例如)一个std::vector,因为链表只是罕见的一个好主意,无论如何。
如果这是家庭作业(或类似的东西),而自己实现链表是整个练习的重点,那么我会先将链表 Package 成一个类,其中包含一些成员函数,以及隐藏在其中的node

class list {

    class node {
        int value;
        node *next = nullptr;

        node(int value, node *next = nullptr) : value(value), next(next) {}
    };

    node *head;
    node *tail;

public:

    void insertHead(int newValue);
    void insertTail(int newValue);
    bool remove(int oldValue);
    void print() const;
};

相关问题