繁体   English   中英

链接列表示例中“this”指的是什么?

[英]What does “this” refer to in Linked List example?

因此,我正在通过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

这是Java。

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

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

链表是一组链接在一起的节点。 当您调用appendToTail()该节点将查看链接到自身的所有Node对象并跟随链。 为了获得对自身的引用以跟随其自己的链,使用this关键字。

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

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

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

让我们假设我们的列表中当前链接了4个对象,为简单起见,调用appendToTail()的Node对象是列表的头部。 这是节点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 ++标签

由于这是一个链接列表,所有节点都已连接,并且您有一个启动节点(根)。 所以当使用它时,它看起来像这样:

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

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

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

Node n = this; 表示对象调用此方法的对象引用。 因此,方法循环到下一个对象,直到下一个对象为空并将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

任何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类来维护对头部的引用,所以你必须能够从任何给定的Node迭代。 这就是这里发生的事情,你从调用了appendToTail Node开始迭代,但是从那个头到尾,那个节点可以是任何东西。

作为旁注,如果你手动实现Linked List,请确保实际上有类LinkedList,它将提供addgetsizeappendToTail等方法,而不是将它们放入Node类。

正如您在此代码中看到的那样

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表示。 Ergo, n也是对节点本身的引用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM