我对C#如何实现链接列表类有一些疑问 第一个问题:
public class Node {
int data;
Node next;
}
它看起来像而不是链接列表,它是一个Big对象,内部具有递归相同的类
我的第二个问题是更具体的,针对如下所示的简单反向链表算法:
public void ReverseList(ref ListNode head){
if(head ==null || head.next == null) return head;
ListNode cur = head;
ListNode prev = null;
ListNode next = head.next;
while (cur != null){
ListNode nextNode = head.next;
cur.next= prev;
prev=cur;
cur=nextNode;
}
head = prev ;
}
不是cur = head是指“ cur”复制所有链接列表元素吗? 而且很难考虑算法中发生了什么。
答案 0 :(得分:6)
它看起来像而不是链接列表,它是一个Big对象,内部具有递归相同的类
Node
是class
,这意味着字段Node next;
是引用(就术语而言,可以与指针广泛互换)。所以不:这绝对是一个链表。 Node
不包含一个Node
。它包含一个字段,该字段是对另一个Node
的引用(认为:指针)。
不是cur = head意味着“ cur”复制了所有链接列表元素吗?
它没有复制任何元素。它正在更改某些现有对象上的引用字段(认为:指针),而就这样。不能复制。但是,这是访问所有元素并更改所有元素上的指针-因此,如果您算上“在所有元素上复制引用(认为:指针)”:当然,它就是这样做的。没有任何分配,等等。
答案 1 :(得分:1)
链接列表使用引用来创建列表结构。
关键是要了解C#中值和引用类型之间的区别。像int
,bool
或struct
这样的值类型实际上是存储在堆栈中的值,当您分配它们时,实际上是在将数据从一个位置复制到另一位置。引用类型在C#中为classes
,区别在于它们只是指向内存堆中数据的指针。默认情况下,它们是null
,您首先必须在堆上为其分配内存,以便它们实际上使用new
指向某个地方。
在这种情况下,您有一个Node
类型的字段作为Node
类的属性,这很好,因为它只是null
或指向其中的另一个位置存储下一个节点的内存堆。如果将class
更改为struct
,则将无法编译,因为这将导致您提到的“递归”问题。但是对于类来说,它只是一个引用,默认值为null
,因此它不必指向实例,实例化Node
仅创建一个{{ 1}}实例在内存中,带有Node
。
这也应该有助于您理解第二个问题-设置next == null
意味着您只是将next = head
指向next
指向内存中的相同位置。您没有移动任何数据,只是在设置参考。
我发现在构建链接列表算法时使用图像会有所帮助。您可以想象每个head
字段就像一个指向某处的箭头。当值为next
时,它仅指向“无处”。最后,当您为null
分配内容时,只需更改箭头指向的位置。