雙鏈結(2)

ListNode

Public Class ListNode Public NodeData As Integer Public NextNode As ListNode Public PrevNode As ListNode End Class

ListNodeLib

' 鏈結程式庫 ' 公用類別 Public Class ListNodeLib ' 首節點 Private Head As ListNode ' 尾節點 Private Tail As ListNode ' 建構子 Public Sub New() Me.Head = Nothing Me.Tail = Nothing End Sub ' 類別屬性 ' 公用唯讀屬性 Public ReadOnly Property ListHead As ListNode Get Return Me.Head End Get End Property ' 類別屬性 ' 公用唯讀屬性 Public ReadOnly Property ListTail As ListNode Get Return Me.Tail End Get End Property ' 公用副程式 ' 加入節點至佇列 Public Sub AddQueue(NewNode As ListNode) If Me.Head Is Nothing Then ' 鏈結無節點時 ' 新節點前後相關位址均為空 NewNode.NextNode = Nothing NewNode.PrevNode = Nothing ' 新節點 -> 首節點 Me.Head = NewNode Else ' 鏈結有節點時 ' 新節點之前節點 = 目前尾節點 NewNode.PrevNode = Me.Tail NewNode.NextNode = Nothing ' 目前尾節點之後節點 = 新節點 Me.Tail.NextNode = NewNode End If ' 尾節點 = 新節點 Me.Tail = NewNode End Sub ' 加入節點至堆疊 Public Sub AddStack(NewNode As ListNode) NewNode.PrevNode = Nothing If Me.Head Is Nothing Then ' 鏈結無節點時 NewNode.NextNode = Nothing ' 新節點 = 首節點 ' 新節點 = 尾節點 Me.Tail = NewNode Else ' 鏈結有節點時 ' 新節點之後節點 = 目前首節點 NewNode.NextNode = Me.Head ' 目前首節點之前節點 = 新節點 Me.Head.PrevNode = NewNode End If ' 目前首節點 = 新節點 Me.Head = NewNode End Sub ' 列印所有節點-FIFO Public Sub PrintList() Dim CurrNode As ListNode = Me.Head Do While Not (CurrNode Is Nothing) Console.Write("{0}{1}", CurrNode.NodeData, vbTab) CurrNode = CurrNode.NextNode Loop Console.WriteLine() End Sub ' 列印所有節點-FILO Public Sub PrintRevList() Dim CurrNode As ListNode = Me.Tail Dim i As Integer = 0 Do While Not (CurrNode Is Nothing) Console.Write("{0}{1}", CurrNode.NodeData, vbTab) CurrNode = CurrNode.PrevNode Loop Console.WriteLine() End Sub ' 依搜尋方向,找出第一個含有特定值之節點 Public Function GetFirstMatchedNode(NodeData As Integer, Foreward As Boolean) As ListNode Dim myListNode As ListNode = Nothing Dim CurrNode As ListNode = IIf(Foreward, Me.Head, Me.Tail) Do While Not (CurrNode Is Nothing) If CurrNode.NodeData = NodeData Then myListNode = CurrNode ' 結束條件迴圈 Exit Do End If If Foreward Then CurrNode = CurrNode.NextNode Else CurrNode = CurrNode.PrevNode End If Loop Return myListNode End Function ' 自當前節點開始,依搜尋方向,找出下一個含有特定值之節點 Public Function GetNextMatchedNode(StartNode As ListNode, NodeData As Integer, Foreward As Boolean) As ListNode Dim myListNode As ListNode = Nothing Dim CurrNode As ListNode = StartNode Do While Not (CurrNode Is Nothing) If Foreward Then CurrNode = CurrNode.NextNode Else CurrNode = CurrNode.PrevNode End If If CurrNode Is Nothing Then Exit Do End If If CurrNode.NodeData = NodeData Then myListNode = CurrNode Exit Do End If Loop Return myListNode End Function Public Sub InsertAfterNode(CurrentNode As ListNode, NodeData As Integer) Dim NextNode As ListNode = CurrentNode.NextNode Dim PrevNode As ListNode = CurrentNode.PrevNode ' 向作業系統要一個新節點 ' 產生新節點之當前位址 (New) Dim NewNode As ListNode = New ListNode NewNode.NodeData = NodeData NewNode.NextNode = Nothing NewNode.PrevNode = Nothing If CurrentNode Is Nothing Then Me.Head = NewNode Me.Tail = NewNode Return End If CurrentNode.NextNode = NewNode NewNode.NextNode = NextNode NewNode.PrevNode = CurrentNode End Sub Public Sub RemoveNode(CurrentNode As ListNode) Dim NextNode As ListNode = CurrentNode.NextNode Dim PrevNode As ListNode = CurrentNode.PrevNode If CurrentNode Is Nothing Then Return End If If CurrentNode Is Me.Head Then Me.Head = NextNode NextNode.PrevNode = Nothing End If If CurrentNode Is Me.Tail Then Me.Tail = PrevNode PrevNode.NextNode = Nothing End If If Not PrevNode Is Nothing Then PrevNode.NextNode = NextNode End If If Not NextNode Is Nothing Then NextNode.PrevNode = PrevNode End If CurrentNode = Nothing End Sub

End Class

主程式

' 模組 Module ModuleW10 ' 宣告私有變數 ' 初始節點程式庫類別 Private MyListNodeLib As ListNodeLib = New ListNodeLib() Sub Init(IsQueue As Boolean) ' 宣告整數陣列 ' 初始陣列 Dim NumArr() As Integer = {11, 21, 31, 1, 9, 8, 21, 7} ' 宣告節點 ' 初始節點類別 Dim CurrListNode As ListNode = Nothing ' 計次迴圈 ' 歷舉陣列元素 For i = 0 To UBound(NumArr) ' 向作業系統要一個新節點 ' 產生新節點之當前位址 (New) CurrListNode = New ListNode ' 賦予新節點資料 CurrListNode.NodeData = NumArr(i) ' 新節點下一節點位址 CurrListNode.NextNode = Nothing ' 新節點前一節點位址 CurrListNode.PrevNode = Nothing If IsQueue Then ' 以佇列方式加入鏈結 (FIFO) MyListNodeLib.AddQueue(CurrListNode) Else ' 以堆疊方式加入鏈結 (FILO) MyListNodeLib.AddStack(CurrListNode) End If Next End Sub Sub Print(Kind As Integer) ' 以位元方式比較 ' 01 If Kind And 1 Then ' 列印鏈結 MyListNodeLib.PrintList() End If ' 10 If Kind And 2 Then ' 反向列印鏈結 MyListNodeLib.PrintRevList() End If End Sub Sub FindNum(Num As Integer) ' 宣告新節點 ' 找尋符合資料之首節點 Dim CurrNode As ListNode = MyListNodeLib.GetFirstMatchedNode(Num, True) ' 條件式迴圈 ' 若找到則繼續尋找下一個符合資料之節點 Do While Not (CurrNode Is Nothing) ' 輸出所找到節點之資料 Console.Write("{0}{1}", CurrNode.NodeData, vbTab) ' 繼續找下一個符合資料之節點 CurrNode = MyListNodeLib.GetNextMatchedNode(CurrNode, Num, True) Loop ' 輸出換行 Console.WriteLine() End Sub Function RemoveFirstNodeForNum(Num As Integer) As Boolean Dim NodeFound As Boolean = False ' 宣告新節點 ' 找尋符合資料之首節點 Dim CurrNode As ListNode = MyListNodeLib.GetFirstMatchedNode(Num, True) If Not CurrNode Is Nothing Then ' 輸出所找到節點之資料 Console.WriteLine("移除:{0}", CurrNode.NodeData) MyListNodeLib.RemoveNode(CurrNode) NodeFound = True End If Return NodeFound End Function ' 主程式 Sub Main() ' 初始鏈結 ' 以堆疊方式加入 Init(False) ' 輸出鏈結 ' 由首至末及由末至首 Print(3) Console.WriteLine("尋找節點 [21]:{0}", vbTab) FindNum(21) Console.WriteLine("在 [1] 之後插入節點 [66]:{0}", vbTab) MyListNodeLib.InsertAfterNode(MyListNodeLib.GetFirstMatchedNode(1, True), 66) ' 輸出鏈結 ' 由首至末及由末至首 Print(3) RemoveFirstNodeForNum(66) ' 輸出鏈結 ' 由首至末及由末至首 Print(3) ' 等待鍵盤輸入 Console.ReadKey() End Sub End Module