Kotlin 我的代码与我在谷歌上找到的检查代码是否正确的代码相比有什么不同?
简而言之,问题是,我想删除双链表的最后一个元素,我编写了这个函数Kotlin 我的代码与我在谷歌上找到的检查代码是否正确的代码相比有什么不同?,kotlin,data-structures,doubly-linked-list,Kotlin,Data Structures,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 =
fun deleteLast(){
if(isEmpty()){println("list is empty")}
if (head!=null && head?.nextNode == null){
head = null
}else {
tail = tail?.previousNode
tail?.nextNode = null
}
}
我在没有遍历的情况下访问了tail,并将其上一个作为newtail,下一个作为newtail(旧tail)设置为null。我的结果是令人满意的。
写完这篇文章后,我点击谷歌来检查这是否正确,所以,我发现了这个
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;
}
}
}
我想问一下我的代码是否正确,我只想让你们大师们检查一下。提前谢谢 问题只包含一个片段,而不是一个,因此为了便于讨论(基于现有代码和注释),我假设完整代码如下所示:
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
}
}
}
类节点(变量previousNode:Node?,变量nextNode:Node?,变量值:T)
类双链接列表(变量头:节点?,变量尾:节点?){
fun isEmpty()=head==null
//…其他方法…
最后的乐趣{
if(isEmpty()){println(“列表为空”)}
if(head!=null&&head?.nextNode==null){
头=空
}否则{
tail=tail?.previousNode
tail?.nextNode=null
}
}
}
鉴于此,您的代码似乎是正确的。 有几点可以解决*,例如:
- 在第二个
中,为了安全起见,我认为还需要将if
设置为nulltail
- 在第二个和第三个分支中,您可能希望将要删除的节点中的
和previousNode
引用设置为null,以便使用仍有引用的任何其他代码。 (这也可能会给垃圾收集器一个额外的提示,尽管不需要)nextNode
- 与其调用
,不如更简单、更一致地检查isEmpty()
是否为nullhead
- 我会在第二个
之前添加一个if
。 事实上,代码适用于空列表,但这可能只是运气;如果其他分支都不能在空列表上调用,那么它将更加健壮。 (在某些情况下,这可能会让编译器智能转换else
为不可空;但在这里不会发生这种情况,因为它是可变的。)head
- 在生产代码中,您不会像那样打印到标准输出。 如果允许对空列表调用
,则无需打印任何内容;如果不是(这更常见),您将抛出一个异常。 (该方法将有一个文档注释来解释这一点。)deleteLast()
- 格式可以改进
头部节点的引用;具有对下一个节点的引用(以及,可能是对存储在节点中的数据的引用);等等 因此,到达列表末尾的唯一方法是遍历所有节点,正如谷歌源代码所做的那样。 (这也意味着通常没有必要使用单独的类来表示整个列表;只需引用第一个节点即可。 使用递归方法可以简洁地编写许多操作。 您还可以使其不可变,这有许多优点;这是某些语言中的主要数据结构。)
但是,您的列表直接引用了最后一个节点,这当然避免了遍历整个列表来查找它。 正如您的代码所演示的,这意味着在双链接列表中某些操作要高效得多。 但也有相应的缺点:每个节点占用更多内存;更改列表时,有更多的引用需要更新;列表更容易进入不一致状态;而且它不太适合于不可变的列表。)如果不查看代码的其余部分,就很难判断这一点。(我试着猜测,但弄不清楚如何将head
、tail
、previousNode
和nextNode
…)它是双链接列表,先生&我在节点类构造函数中声明previous、next和node值,在双链接列表类主体中声明head和tail作为类型节点。先生,您解决了我的问题!非常感谢你!