【问题标题】:given a node how can I find previous node in a singly linked list给定一个节点如何在单链表中找到前一个节点
【发布时间】:2011-11-04 03:19:59
【问题描述】:

给定当前节点,如何在单链表中找到它的前一个节点。谢谢。逻辑会做,代码表示赞赏。我们都知道给定一个根节点可以进行顺序遍历,我想知道是否有一种更智能的方法可以避免顺序访问开销。 (假设无法访问根节点)谢谢。

【问题讨论】:

  • 这里的代码也可以回答这个问题。
  • 所以我明白了,你想知道你给你号码的那个女孩的号码????????

标签: java c list data-structures linked-list


【解决方案1】:

你不能。

根据定义,单链表仅将每个节点链接到其后继节点,而不是前驱节点。没有关于前身的信息;甚至没有关于它是否存在的信息(您的节点可能是列表的头部)。

您可以使用双向链表。 您可以尝试重新排列所有内容,以便首先将前任作为参数传入。

您可以扫描整个堆以查找看起来像前驱节点并带有指向您节点的指针的记录。 (不是一个严肃的建议。)

【讨论】:

  • 你为什么说“你不能”?从列表的开头迭代搜索“下一个”等于“当前”的节点有什么问题。如果没有找到匹配返回NULL 或类似的东西??
  • “你不能”的意思是“这在数学上是不可能的”。缺少一条无法重新创建的信息。这个问题(我认为)很明显,他们甚至无法访问列表的头部;所以没有已知的起点可以迭代您建议的方式。
  • 要跟进,如果您确实可以访问列表的头部,那么您可以按照我的建议“重新排列所有内容,以便拥有前任传入”。
  • @hemflit:我很难相信有人拥有一个不允许访问列表头的(非伪造的)链接列表容器。这样一个容器有什么意义?您只能将项目推送到列表中,但永远无法迭代它们......
  • Darren,他们没有使用一些库容器。他们甚至没有在这个问题的容器级别上工作,而是在原始数据结构的级别上工作,直接处理列表节点中的指针,实际上是从头开始编码“容器”。他们谈论的是执行点,不是整个列表都可以访问,而只能访问单个节点以及可以从该节点找到的所有内容。否则问题将是“给定一个列表”,而不是“给定当前节点”。
【解决方案2】:

从头开始遍历列表,直到遇到一个节点,其 next 链接指向您当前的节点。

但如果你需要这样做,也许你一开始就不应该使用单链表。

【讨论】:

    【解决方案3】:

    单链表的唯一选择是线性搜索,如下所示(类似 Python 的伪代码):

    find_previous_node(list, node):
       current_node = list.first
       while(current_node.next != null):
           if(current_node.next == node):
              return current_node
           else:
              current_node = current_node.next
       return null
    

    【讨论】:

      【解决方案4】:

      如果要删除当前节点,也可以不查找前一个节点。

      Python 代码:

      def deleteNode(self, node):

      node.val = node.next.val
      
      node.next = node.next.next
      

      @删除链表中的节点

      【讨论】:

      • 这应该是公认的答案。其他人似乎都忘记了头部是不可访问的,只给出了一个节点。但是,需要注意的一点是,如果给定节点是单链表的 Tail,则此解决方案将不起作用。
      【解决方案5】:

      假设您正在谈论一个正向单链表(每个节点只有一个指向“下一个”等的指针),您将不得不从列表的开头进行迭代,直到找到“下一个”等于的节点到您当前的节点。显然,这是一个缓慢的O(n) 操作。

      希望这会有所帮助。

      【讨论】:

        【解决方案6】:

        保持两个指针(curr,prev)最初都将指向列表的头部。

        在列表上循环,直到到达列表的末尾或所需的节点。

        对于每次迭代,将 curr 节点移动到它的下一个,但在移动到下一个之前,将其指针存储在 prev 指针中。

            prev = curr; // first store current node in prev
            curr = curr->next // move current to next
        

        在循环结束前一个节点将包含前一个节点。

        getPrev(head, key) {    
            Node* curr = head;
            Node* prev = head;
            while(curr !=null && curr->data==key){
                prev = curr;
                curr = curr->next
            }
            return prev
        }
        

        示例:

        列表 = 1->5->10->4->3

        我们想要 4 的 prev 节点,所以 key = 4 和 head point 在 1 这里

        最初:

        • temp 将指向 1
        • prev 将指向 1

        迭代 1:

        • 首先,分配 prev=temp(prev 指向 1)
        • 移动温度; temp->next(温度指向 5)

        迭代 2:

        • 首先,分配 prev=temp(prev 指向 5)
        • 移动温度; temp->next(温度指向 10)

        迭代 3:

        • 首先,分配 prev=temp(prev 指向 10)
        • 移动温度; temp->next(温度指向 4)

        迭代 4:

        • temp->data == 键,因此它将退出循环。
        • 返回上一个节点

        【讨论】:

        • 感谢您提供此代码 sn-p,它可能会提供一些有限的短期帮助。一个正确的解释would greatly improve 其长期价值,通过展示为什么这是解决问题的好方法,并将使其对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。
        【解决方案7】:

        这是我在解决问题时发现的某种技巧(删除列表中的每个偶数节点)

            internal void DeleteNode(int p)
            {
                DeleteNode(head, p);
            }
        
            private void DeleteNode(Node head, int p)
            {
                Node current = head;
                Node prev = null;
        
                while (current.next != null)
                {
                    prev = current;
                    current = current.next;
                    if (current.data == p)
                    {
                        prev.next = current.next;
                    }
                }
            }
        

        现在在这里,在 prev 中分配当前节点,然后将当前节点移动到下一个节点,从而 prev 包含前一个节点。 希望这会有所帮助...

        【讨论】:

          【解决方案8】:

          使用 nodeAt() 方法并传递当前节点的头、大小和索引。

           public static Node nodeAt(Node head,int index){
              Node n=head;
              for(int i=0;i<index;i++,n=n.next)
                ;
              return n;
            }
          

          其中 n 返回前任的节点。

          【讨论】:

            【解决方案9】:

            这是线性搜索的一个小技巧:只需传入要搜索的上一个节点的节点或其位置即可:

            private MyNode findNode(int pos) {
            //node will have pos=pos-1
                    pos-- = 1; 
                    MyNode prevNode = null;
                    int count = 0;  
                    MyNode p = first.next;  // first = head node, find it however you want.
            //this is for circular linked list, you can use first!=last for singly linked list
                    while (p != first) { 
                        if (count == pos) {
                            prevNode = p;
                            break;
                        }
                        p = p.next;
                        count++;
                    }
                    return prevNode;
                }
            

            【讨论】:

              【解决方案10】:

              我们可以使用慢速和快速指针遍历 LinkedList。 比方说

              快速指针fast = fast.next.next

              慢指针slow = slow.next

              慢指针总是在快指针之前,所以我们可以找到它。

              【讨论】:

                【解决方案11】:

                你可以这样做..你可以用下一个节点的值替换当前节点的值..并且在第二个最后一个节点的下一个你可以放空。就像从字符串中删除一个元素一样。这是代码

                void deleteNode(ListNode* node) {
                    ListNode *pre=node;
                   while(node->next) 
                    {
                        node->val=node->next->val;
                        pre=node;
                        node=node->next;
                    }
                    pre->next=NULL;
                

                }

                【讨论】:

                  【解决方案12】:

                  假设您使用正向单链表,您的代码应该如下所示

                  while(node)
                  {
                        previous = node
                        node = node.next
                        // Do what ever you want to do with the nodes
                  }
                  

                  【讨论】:

                  • if(node.content == whatINeed) { doSomething(previous.content); }.
                  猜你喜欢
                  • 2018-09-29
                  • 2021-08-02
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-12-23
                  • 1970-01-01
                  • 2017-07-14
                  • 2014-08-02
                  • 2021-11-24
                  相关资源
                  最近更新 更多