微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

与我在 Google 上找到的用于检查我的代码是否正确的代码相比,我的代码有何不同?

如何解决与我在 Google 上找到的用于检查我的代码是否正确的代码相比,我的代码有何不同?

简而言之,问题是,我想删除 DOUBLY LINKED LIST 的最后一个元素,我写了这个函数...

fun deleteLast(){
    if(isEmpty()){println("list is empty")}
    if (head!=null && head?.nextNode == null){
        head = null
    }else {
        tail = tail?.prevIoUsNode
        tail?.nextNode = null
    }
}

我没有遍历它就走到了尾部,并将它的前一个作为新尾部和新尾部下一个(旧尾部)为空。我的结果是可取的。 写完这篇后,我 ping 谷歌检查这是否正确,我发现了这个......

void pop_back() {
if(this.head != null) {
//1. if head in not null and next of head
//   is null,release the head
if(this.head.next == null) {
  this.head = null;
} else {
  
  //2. Else,traverse to the second last 
  //   element of the list
  Node temp = new Node();
  temp = this.head;
  while(temp.next.next != null)
    temp = temp.next;
  
  //3. Change the next of the second 
  //   last node to null and delete the
  //   last node
  Node lastNode = temp.next;
  temp.next = null; 
  lastNode = null;
  }
 }
}

我想问一下我的代码是否正确,我只希望各位高手审核一下。提前致谢!

解决方法

问题只包含一个片段,而不是一个 minimal,reproducible example,所以为了论证(基于现有代码和评论),我将假设完整代码如下所示:>

class Node<T>(var previousNode: Node<T>?,var nextNode: Node<T>?,var value: T)

class DoublyLinkedList<T>(var head: Node<T>?,var tail: Node<T>?) {
    fun isEmpty() = head == null

    // …other methods…

    fun deleteLast(){
        if(isEmpty()){println("list is empty")}
        if (head!=null && head?.nextNode == null){
            head = null
        }else {
            tail = tail?.previousNode
            tail?.nextNode = null
        }
    }
}

鉴于此,看起来您的代码是正确的。有几点可以解决*,例如:

  • 在第二个 if 中,为了安全,我认为它也需要将 tail 设置为 null。
  • 在第二个和第三个分支中,您可能希望将要删除的节点中的 previousNodenextNode 引用设置为空,以方便任何其他仍然具有引用的代码到它。 (这也可能给垃圾收集器一个额外的提示,尽管这不是必需的。)
  • 与调用 isEmpty() 相比,检查 head 是否为 null 会更简单、更一致。
  • 我会在第二个 else 之前添加一个 if。实际上,该代码适用于空列表,但这可能只是运气;如果其他分支都不能在空列表上调用,它会更加健壮。 (在某些情况下,这可能让编译器将 head 智能转换为不可为空;但这里不会发生这种情况,因为它是可变的。)
  • 在生产代码中,您不会像那样打印到标准输出。如果允许在空列表上调用 deleteLast(),则无需打印任何内容;如果不是(这会更常见),你会抛出一个异常。 (并且该方法会有一个文档注释来解释这一点。)
  • 格式可以改进。

(*根据我的经验,任何代码都可以改进——即使是你以前处理过很多次的代码!)

但是,您不能直接将您的代码与来自 Google 的代码进行比较,因为它看起来像是用于单向链接的列表。

单向链表是一种简单得多的结构。它所拥有的只是对 head 节点的引用;具有对 next 节点的引用(并且大概是对存储在节点中的数据的引用);等等。因此,到达列表末尾的唯一方法是遍历所有节点,就像 Google 源代码所做的那样。 (这也意味着通常没有必要使用单独的类来表示整个列表;您只需要对第一个节点的引用即可。 许多操作可以用递归方法简洁地编写。 您也可以使其不可变,即有很多优点;这是某些语言中的主要数据结构。)

然而,您的列表直接引用了最后一个节点,这当然避免了遍历整个列表来查找它的需要。正如您的代码所示,这意味着某些操作在双链表中效率更高。但也有相应的缺点:每个节点占用更多内存;更改列表时有更多引用要更新;列表更容易进入不一致状态;它不太适合不可变列表。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。