Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Data structures 当只给出指向某个节点的指针时,从单个链接列表中删除该节点_Data Structures_Linked List - Fatal编程技术网

Data structures 当只给出指向某个节点的指针时,从单个链接列表中删除该节点

Data structures 当只给出指向某个节点的指针时,从单个链接列表中删除该节点,data-structures,linked-list,Data Structures,Linked List,这是在一次采访中向我提出的一个问题 内存中有一个单一的链表。您必须删除一个节点。您需要编写一个函数来删除该节点,该函数只将要删除的节点的地址作为输入,不接受任何其他内容(包括头) 我给出的答案与下面帖子中的答案类似——将下一个节点的内容复制到要删除的节点中,然后删除下一个节点 但是面试官又问我,如果我传递最后一个节点的地址会怎么样。我告诉他,因为下一个将是NULL,所以将该NULL与下一个节点的地址(也是NULL)一起复制到数据字段中。然后他告诉我会有悬空指针的问题。。。我一点也不明白。有人能

这是在一次采访中向我提出的一个问题

内存中有一个单一的链表。您必须删除一个节点。您需要编写一个函数来删除该节点,该函数只将要删除的节点的地址作为输入,不接受任何其他内容(包括头)

我给出的答案与下面帖子中的答案类似——将下一个节点的内容复制到要删除的节点中,然后删除下一个节点

但是面试官又问我,如果我传递最后一个节点的地址会怎么样。我告诉他,因为下一个将是NULL,所以将该NULL与下一个节点的地址(也是NULL)一起复制到数据字段中。然后他告诉我会有悬空指针的问题。。。我一点也不明白。有人能解释一下这个问题吗?有没有通用的解决方案

更新(两天后):增加一点。考虑到列表末尾没有特殊节点。最后一个节点指向NULL,如果该节点作为输入给定,那么如何使前一个节点指向NULL。还是不可能


简单地说:如果一个节点作为一个函数的输入,如何使引用它的指针指向NULL

如果有其他元素指向下一个节点,这些元素将被复制到当前节点,然后被删除,那么这个操作将引入错误。因此,在您的回答中,您应该强调,您的解决方案只有在没有外部引用列表的情况下才有效

只有当数据结构使用特定的“last node”元素进行扩充时,您的解决方案才能使用最后一个节点。(如果您使用的是Smalltalk,您可以编写
self-been:nil
任何其他语言都没有类似的功能)

不,如果列表有外部引用,则没有通用解决方案。我想面试官想看看你是否真的精通这个主题,或者只是在重复一个记忆中的答案。

悬空指针:

(http://en.wikipedia.org/wiki/Dangling_reference)

计算机编程中的悬空指针和野指针是 不指向适当类型的有效对象的指针。 这些是内存安全违规的特殊情况

当对象被删除或解除分配时,会出现悬空指针, 不修改指针的值,使指针仍然 指向解除分配内存的内存位置。作为系统 如果 然后原始程序取消引用(现在)悬空指针, 可能会导致不可预测的行为,因为内存现在可能包含 完全不同的数据

在您的回答中,要删除给定节点,实际上是删除下一个节点,该节点可能被指针引用。这就是悬空指针问题产生的原因

(1) 正如您在注释中所阐明的,该列表没有外部参考。 (2) 正如采访者所说,悬空指针问题可能会出现

(1)和(2)不能同时正确。这意味着某个地方有误会

关于删除最后一个节点:

但是面试官又问我,如果我把面试官的地址传过去怎么办 最后一个节点。我告诉他,既然下一个是空的,复制那个空的 与下一个节点的地址一起输入数据字段,该节点是 也为空

我认为您混淆了这两件事:(1)指向NULL的指针p,(2)数据字段中有NULL的链表节点

假设数据结构是
a->b->c->d
。将NULL写入d的数据字段不会神奇地使c在其
next
字段中有NULL指针

如果链表始终有一个永远不会删除的特殊最后节点,则可以删除最后一个节点。例如,
a->b->c->d->LAST
其中LAST在其数据字段中有一个特殊值,表示它实际上是最后一个元素。现在要删除d,可以删除最后一个,并在d的数据字段中写入特殊值

也许这些正是你在面试中想要说的,在这种情况下,你和面试官之间一定有一些沟通错误。

步骤:

  • 将数据从节点(i+1)复制到节点(i)
  • 将第二个节点(i+1)的下一个节点复制到临时变量中
  • 现在删除第二个节点(i+1)//它不需要指向前一个节点的指针
  • 功能:

    void delete_node(node* node)
    {
        node->Data = node->Next->Data;
        node* temp = node->Next->Next;
        delete(node->Next);
        node->Next = temp;
    }
    

    可能您的链接列表遍历可能需要假设指向
    null
    的任何节点都是
    null
    节点,而不管值是多少

    a->b->c->d->NULL
    

    因此
    d
    null
    节点,不应将该节点视为节点。这样可以节省使用特殊值的时间,因为它们在一般意义上是不正确的。除此之外,您将没有任何其他方法使上一个节点指向
    null

    然后应该有一个签入程序,检查给定节点是否是最后一个节点

    void delete_node(node* node1)
    {
        node* search=head;
        if(node1==head)
        {
            head=head->next;
            search->next=NULL;
            node1->next=NULL;
        }
        while(search->next != node1)
            search=search->next;
        if(node1->next==NULL)
        {
           search->next=NULL;
        }
        else
        {
           search->next=node1->next;
           node1->next=NULL;
        }
        delete node1;
    }
    

    假设:deleteNode()引用了节点指针

    没有while循环的简单解决方案。在deleteNode()中,if case处理头节点和中间节点的删除,而else处理最后一个节点的删除

    #include <iostream>
    using namespace std;
    
    class Node{
    
    public:
      int data;
      Node* next;
    
      Node(int d): data(d){}
    };
    
    void insert(Node* &head,  int data){
      Node *node = new Node(data);
      node->next = head;
      head = node;
    }
    
    void print(Node *head){
      Node *temp = head;
      while(temp !=NULL){
        cout << temp->data <<" ";
        temp = temp->next;
      }
      cout << endl;
    }
    
    void deleteNode(Node *&node){
    
      cout << "Deleting "<<node->data<<endl;
      if(node->next != NULL){
        Node *t = node->next;
        node->data = node->next->data;
        node->next = node->next->next;
    
        delete t;
      }else{
        delete node;
        node = NULL;
      }
    }
    
    int main(int argc, char const *argv[]) {
    
      Node *head = NULL;
      insert(head, 10);
      insert(head, 20);
      insert(head, 30);
      insert(head, 40);
      insert(head, 50);
    
      print(head);
    
      deleteNode(head->next); //delete 40
      deleteNode(head->next->next->next); //delete last node 10
    
      print(head);
    
      return 0;
    }
    
    #包括
    使用名称空间std;
    类节点{
    公众:
    int数据;
    节点*下一步;
    节点(intd):数据(d){}
    };
    无效插入(节点*&头部,整数数据){
    节点*节点=新节点(数据);
    节点->下一步=头部;
    头部=节点;
    }
    无效打印(节点*头){
    节点*温度=头部;
    while(temp!=NULL){
    cout data next=节点->下一步->下一步;
    删除t;
    }否则{
    删除节点;
    node=NULL;
    }
    }
    int main(int argc,char const*argv[]{
    Node*head=NULL;
    插入(头,10);
    插入(头,20);
    插入(头,30);
    插入(头,40);
    插入(头,50);
    打印头;
    删除节点(
    
    #include <iostream>
    using namespace std;
    
    class Node{
    
    public:
      int data;
      Node* next;
    
      Node(int d): data(d){}
    };
    
    void insert(Node* &head,  int data){
      Node *node = new Node(data);
      node->next = head;
      head = node;
    }
    
    void print(Node *head){
      Node *temp = head;
      while(temp !=NULL){
        cout << temp->data <<" ";
        temp = temp->next;
      }
      cout << endl;
    }
    
    void deleteNode(Node *&node){
    
      cout << "Deleting "<<node->data<<endl;
      if(node->next != NULL){
        Node *t = node->next;
        node->data = node->next->data;
        node->next = node->next->next;
    
        delete t;
      }else{
        delete node;
        node = NULL;
      }
    }
    
    int main(int argc, char const *argv[]) {
    
      Node *head = NULL;
      insert(head, 10);
      insert(head, 20);
      insert(head, 30);
      insert(head, 40);
      insert(head, 50);
    
      print(head);
    
      deleteNode(head->next); //delete 40
      deleteNode(head->next->next->next); //delete last node 10
    
      print(head);
    
      return 0;
    }