我目前正在编写一个程序(截至目前)使用大约五个链接列表,并且大约有50个函数可以修改或以其他方式使用这些链接列表。我对头节点应该如何实现有点不知所措。
实施#1 使用虚拟头节点
如果我创建一个虚拟头节点,则永远不必删除headNode,即使该链表没有数据可以表示。以下是显示此想法的两个不同的可能链接列表。
Format: (object)--name_of_pointer_to_next_object--> (next object)
(headNode)--headNode.pNext--> (Nothing/NULL)
(headNode)--headNode.pNext--> (dataNode1)--dataNode1.pNext--> (dataNode2)--dataNode2.pNext--> (Nothing/NULL)
此实现的好处是,对于使用链接列表的函数,它们不必具有头节点为Nothing
或(在c ++中){{{ 1}}。下面是使用此实现将节点附加到链接列表末尾的示例。
NULL
实施#2 可以删除headNode
如果我允许删除headNode,则会出现问题并增加我必须编写的代码量。下面是相同的数据集,但这次头部是包含数据的合法节点。
Public Function AppendNode(theLinkedList as NODE_, theNewNode as NODE_)
dim lastNode as NODE_
Set lastNode = theLinkedList
Do While Not lastNode.pNext Is Nothing
Set lastNode = lastNode.pNext
Loop
Set lastNode.pNext = theNewNode
End Function
这是相同的功能,除了这次它必须要注意头节点是Format: (object)--name_of_pointer_to_next_object--> (next object)
(Nothing/NULL)
(dataNode1)--dataNode1.pNext--> (dataNode2)--dataNode1.pNext--> (Nothing/NULL)
/ Nothing
的可能性。
NULL
显然,我倾向于实施#1。每次我想要使用链接列表时,它至少需要4行代码(考虑到我将这样做数百次,你可以将这4行乘以300左右;例如它可以节省我写入1,200行代码),也许最重要的是,它会减少我的程序所具有的状态量。我的程序所处的所有可能状态只需要我查找Public Function AppendNode(theLinkedList as NODE_, theNewNode as NODE_)
dim lastNode as NODE_
If theLinkedList Is Nothing Then
Set theLinkedList = theNewNode
Else
Set lastNode = theLinkedList
Do While Not lastNode.pNext Is Nothing
Set lastNode = lastNode.pNext
Loop
Set lastNode.pNext = theNewNode
End If
End Function
,并且此时减少状态量非常受欢迎,因为这个程序将成为一个怪物,最终会成为一个怪物。大约20k行相当复杂的代码,必须处理很多状态。
我认为实施#1是最好的方法吗?我无法想出为什么实施#2会更优越的原因。
答案 0 :(得分:1)
在链表的开头和结尾有一个特殊的保留节点是很常见的(虽然不是必需的)。它通常称为sentinel node。
顺便说一句,我建议使用“大约50个修改或以其他方式使用这些链接列表的函数”并将它们移动到封装它们的类中。
你不应该有这样的代码:
Dim theLinkedList as NODE_
Set theLinkedList = New NODE_
'bunch of work with the list
'bunch of work with the list
'bunch of work with the list
Dim theNewNode as NODE_
Set theNewNode = New NODE_
Set theNewNode.Next = someDataObject
Call AppendNode(theLinkedList, theNewNode)
相反,代码应如下所示:
Dim theList As LinkedList
Set theList = New LinkedList
'etc
Call theList.Append(someDataObject)
看到区别? LinkedList calss包装并隐藏细节。它可以处理诸如头部或尾部是否有前哨节点之类的事情,以便项目代码的所有其余部分都没有意识到。