"this"在链表示例中指的是什么?



所以我浏览了破解编码面试来复习一些面试内容,我浏览了这个链表实现,也许已经有一段时间了,但它完全超出了我的想象。除了一行,我理解了大部分内容,这让我很困惑。我会在下面发布代码(作为参考,这本书没有提到语言,但看起来是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

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++标记

这就是Java。

"this"是指进行调用的类的特定实例。在这种情况下,"this"是指您正在处理的特定类Node。而变量"end"创建了Node类的单独版本,该类是使用传递的int"d"构造的。

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

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

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

当将n设置为null并将while从this.next重写时,如果使用appendToTail的当前节点没有下一个node,则会引发NullPointerException。

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

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

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也是对所述节点本身的引用

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

请注意,事实上Node并没有将自己附加到列表的尾部,这里发生的是创建新节点并将其添加到尾部,而不是调用方法的节点。

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

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

一旦我们找到下一个==为null的节点,这就是列表的尾部,所以我们现在可以将新的Node附加到尾部:

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

至于为什么有行:

    Node n = this;

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

顺便说一句,如果您手动实现LinkedList,请确保确实有LinkedList类,它将提供addgetsizeappendToTail等方法,而不是将这些方法放入Node类中。

相关内容

  • 没有找到相关文章