【问题标题】:What does "this" refer to in Linked List example?链接列表示例中的“this”指的是什么?
【发布时间】:2015-08-12 18:06:50
【问题描述】:

所以我正在浏览 Cracking the Coding Interview 以复习一些面试内容,然后我遇到了这个链表实现,也许已经有一段时间了,但它完全超出了我的想象。我了解其中的大部分内容,除了一条特定的线路,这让我很反感。我将代码贴在下面(供参考,书中没有提到语言但似乎是Java。)

class Node {
    Node next  = null;
    int data;

    public Node(int d) {
        data = d;
    }

    void appendToTail(int d) {
        Node end = new Node(d);
        Node n = this;
        while(n.next != null) {
            n = n.next;
        }
        n.next = end;
    }
}

我有点困惑:Node n = this - 我不确定this 指的是什么,除非它在谈论next - 在这种情况下为什么不把它设置为null ?

【问题讨论】:

  • 这不是 C++。可能是 Java 吗?
  • 提示:你怎么称呼appendToTail
  • 这绝对是Java
  • @Barry 我也这么想,问了一个朋友,他们说它看起来像 C++。感谢您的澄清!

标签: java linked-list


【解决方案1】:

this 指的是类对象的特定实例。由于对象是构造的,一个类可以有多个实例,但是使用this 关键字可以让您获得对自身的引用,这意味着对正在调用其方法的对象的特定实例的引用。

链表是节点的集合,它们是链接在一起的。当您调用appendToTail() 时,节点将查看链接到自身的所有节点对象并遵循链。为了让它引用自己以跟随它自己的链,使用了this 关键字。

您还问为什么在这种情况下不使用null 来初始化n。这将在循环约束中首次调用n.next 时导致NullPointerException,因此它自己的引用被用作链表迭代的起点。

这个(双关语)起初可能是一个令人困惑的话题,但让我们使用您提供的示例。

Node n = this;
while(n.next != null) {
    n = n.next;
}

假设我们的列表中当前有 4 个对象链接,为简单起见,正在调用 appendToTail() 的 Node 对象是列表的头部。这是上述 sn-p 在每次循环迭代中保存的节点 n 的参考值。

  1. 我们指向我们自己 - this
  2. 指向链表中的第二项。 - this.next
  3. 指向以下项目 - this.next.next
  4. 指向列表中的最后一项 - this.next.next.next

循环结束,所以当前引用了n = this.next.next.next。然后我们将n 的下一个值(n 当前指向链接链的末尾)设置为我们在方法开头创建的新对象,这使其成为列表的新结尾。 (n.next = end 现在等同于this.next.next.next.next = end)。

半不必要的编辑:这是用 Java 解释的。在我写完这个答案之后,似乎有人添加了 C++ 标签

【讨论】:

    【解决方案2】:

    这是Java。

    this”指的是调用所在类的特定实例。在这种情况下,“this”是指您正在处理的特定类Node。而变量“end”创建了一个 new 和单独版本的 Node 类,它是使用传递的 int “d”构造的。

    【讨论】:

    • 你的第二句话有点误导:this 不指类本身,这意味着它是一个静态方法。相反,它指的是调用该方法的类的特定实例。我的意思不是听起来很迂腐,但这是一个令人困惑的话题,所以只是想确保它清楚。
    • 是的,很公平。清除后的句子,但我在您的建议中进行了编辑。谢谢。
    【解决方案3】:

    由于这是一个链接列表,所有节点都已连接,并且您有一个起始节点(根)。所以在使用的时候会是这样的:

    Node root = new Node(6); //need an instance first
    root.appendToTail(5);
    root.appendToTail(3);
    //6->5->3
    

    由于这个节点已连接,我需要一个起始节点,并且需要检查它是否有下一个节点,如果是,我需要更深入地搜索。当一个节点没有 next 节点时,它是当前的最后一个节点,可以添加我的新节点。所以 Java 中的 this 指的是一个类的当前实例。在我的示例中,root 节点(因为我调用了 root.appendToTail)。因此,该方法将从 root 节点(值为 6)搜索下一个没有 next 节点的节点(值为 3 的节点)并将其附加到那里。如果我可以获得子引用并调用 child3.appendToTail,则该方法将从 child3 搜索,而不是从我的根目录开始。

    当将 n 设置为 null 并从 this.next 重写 while 时,当您使用 appendToTail 的当前节点没有下一个节点时,您会遇到问题并且会抛出 NullPointerException。

    【讨论】:

      【解决方案4】:

      Node n = this; 表示 n 个对象引用到正在调用此方法的对象。 因此方法循环到下一个对象,直到下一个对象为空并将end 节点分配到末尾。

      让我们看看

      1 -- 2 -- 3 -- 4
      *
      |
      *
      obj
      

      你有一个指向节点 1 的 obj 对象。当你调用 obj.appendToTail(5)

      Node end = new Node(d); //new node is created to add to the end.
      Node n = this; //local n object is referenced to node 1(or obj)
      while(n.next != null) {
         n = n.next;
      }
      //n here is node 4 since there is no next node to 4
      n.next = end; //node 5 is tail now
      

      最终结果: 1 -- 2 -- 3 -- 4 -- 5

      【讨论】:

        【解决方案5】:

        正如你在这段代码中看到的

        class Node {
           //
        
           void appendToTail( int d ) {
               Node *end = new Node( d );
               Node n = this;
               // ...
           }
        }  
        

        您的课程Node 在其定义中引用了Node

        行:Node *end = new Node( d ); 表示在Node 内有对另一个节点的引用。

        Node n = this; 行表示在Node 中对该节点本身 的引用,由this 表示。因此,n 也是对所述节点本身的引用。

        【讨论】:

          【解决方案6】:

          任何 Node 实例都可以调用appendToTail()

          注意howebet,实际上Node 确实 将自己附加到列表的尾部,这里发生的是新节点被创建并添加到尾部,而不是方法所在的那个调用。

          为此,首先我们需要在给定当前Node 的情况下找到列表的尾部。

            // n is pointing to current Node
            while(n.next != null) {
                      n = n.next;
                  }
          

          一旦我们找到具有 next == null 的节点,这是列表的尾部,因此我们现在可以将新的 Node 附加到尾部:

              // n points to current tail before next line is invoked
              n.next = end;
          

          至于为什么会有线:

              Node n = this;
          

          因为没有LinkedList 类维护对头部的引用,所以你必须能够从任何给定的节点进行迭代。这就是这里发生的情况,您从调用 appendToTail 的 Node 开始迭代,但此时 Node 可以是任何东西,从头到尾。

          附带说明,如果您手动实现 LinkedList,请确保实际上有 LinkedList 类,它将提供诸如 addgetsizeappendToTail 等方法,而不是将这些放入 Node 类中。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-10-14
            • 2016-03-26
            • 1970-01-01
            • 2019-06-12
            • 2019-01-19
            • 2013-05-05
            • 2016-04-06
            • 1970-01-01
            相关资源
            最近更新 更多