浏览代码

Added TLinkedList.

woollybah 6 年之前
父节点
当前提交
63249d66a7

+ 1 - 0
collections.mod/collections.bmx

@@ -9,3 +9,4 @@ Import "map.bmx"
 Import "list.bmx"
 Import "list.bmx"
 Import "queue.bmx"
 Import "queue.bmx"
 Import "stack.bmx"
 Import "stack.bmx"
+Import "linkedlist.bmx"

+ 20 - 0
collections.mod/doc/tlinkedlist_addlast.bmx

@@ -0,0 +1,20 @@
+SuperStrict
+
+Framework brl.collections
+Import brl.standardio
+
+Local cities:TLinkedList<String> = New TLinkedList<String>
+
+cities.AddLast("Shanghai")
+cities.AddLast("Beijing")
+cities.AddLast("Guangzhou")
+cities.AddLast("Shenzhen")
+cities.AddLast("Tianjin")
+cities.AddLast("Shanghai")
+cities.AddLast("Wuhan")
+
+For Local city:String = EachIn cities
+	Print city
+Next
+
+Print "Count = " + cities.Count()

+ 8 - 0
collections.mod/errors.bmx

@@ -51,3 +51,11 @@ Type TArgumentException Extends TBlitzException
 	End Method
 	End Method
 
 
 End Type
 End Type
+
+Type TArgumentNullException Extends TArgumentException
+
+	Method New(arg:String)
+		Self.message = arg + " cannot be null"
+	End Method
+
+End Type

+ 411 - 0
collections.mod/linkedlist.bmx

@@ -0,0 +1,411 @@
+SuperStrict
+
+Import "collection.bmx"
+
+Rem
+bbdoc: A doubly linked list.
+End Rem
+Type TLinkedList<T> Implements ICollection<T>
+Private
+	Field head:TLinkedListNode<T>
+	Field size:Int
+Public
+
+	Rem
+	bbdoc: Creates a new #TLinkedList initialised by @array.
+	End Rem
+	Method New(array:T[])
+		If array Then
+			For Local value:T = EachIn array
+				AddLast(value)
+			Next
+		End If
+	End Method
+
+	Rem
+	bbdoc: Creates a new #TLinkedList initialised by @iterable.
+	End Rem
+	Method New(iterable:IIterable<T>)
+		If iterable Then
+			For Local value:T = EachIn iterable
+				AddLast(value)
+			Next
+		End If
+	End Method
+
+	Rem
+	bbdoc: Returns an iterator that iterates through the #TLinkedList.
+	End Rem
+	Method GetIterator:IIterator<T>()
+		Return New TLinkedListIterator<T>(Self)
+	End Method
+
+	Rem
+	bbdoc: Gets the number of nodes contained in the #TLinkedList. 
+	End Rem
+	Method Count:Int()
+		Return size
+	End Method
+
+	Method CopyTo(array:T[], index:Int = 0)
+		' TODO
+	End Method
+
+	Rem
+	bbdoc: Gets the first node of the #TLinkedList.
+	End Rem
+	Method First:TLinkedListNode<T>()
+		Return head
+	End Method
+	
+	Rem
+	bbdoc: Gets the last node of the #TLinkedList.
+	End Rem
+	Method Last:TLinkedListNode<T>()
+		If head Then
+			Return head.PreviousNode
+		Else
+			Return Null
+		End If
+	End Method
+	
+	Rem
+	bbdoc: Adds a new node containing the specified @value after the specified existing @node in the #TLinkedList.
+	returns: The new node.
+	End Rem
+	Method AddAfter:TLinkedListNode<T>(node:TLinkedListNode<T>, value:T)
+		ValidateNode(node)
+		
+		Local newNode:TLinkedListNode<T> = New TLinkedListNode<T>(Self, value)
+		
+		InsertNodeBefore(node.nextNode, newNode)
+		
+		Return newNode
+	End Method
+	
+	Rem
+	bbdoc: Adds the specified @newNode after the specified existing @node in the #TLinkedList.
+
+	End Rem
+	Method AddAfter(node:TLinkedListNode<T>, newNode:TLinkedListNode<T>)
+		ValidateNode(node)
+		ValidateNewNode(newNode)
+		
+		InsertNodeBefore(node.nextNode, newNode)
+		newNode.list = Self
+	End Method
+	
+	Rem
+	bbdoc: Adds a new node containing the specified @value before the specified existing @node in the #TLinkedList.
+	returns: The new node.
+	End Rem
+	Method AddBefore:TLinkedListNode<T>(node:TLinkedListNode<T>, value:T)
+		ValidateNode(node)
+		Local newNode:TLinkedListNode<T> = New TLinkedListNode<T>(Self, value)
+
+		InsertNodeBefore(node, newNode)
+
+		If node = head Then
+			head = newNode
+		End If
+		
+		Return newNode
+	End Method
+	
+	Rem
+	bbdoc: Adds the specified @newNode before the specified existing node in the LinkedList<T>.
+	End Rem
+	Method AddBefore(node:TLinkedListNode<T>, newNode:TLinkedListNode<T>)
+		ValidateNode(node)
+		ValidateNewNode(newNode)
+		
+		InsertNodeBefore(node, newNode)
+		newNode.list = Self
+		
+		If node = head Then
+			head = newNode
+		End If
+	End Method
+	
+	Rem
+	bbdoc: Adds the specified new @node at the start of the #TLinkedList.
+	End Rem
+	Method AddFirst(node:TLinkedListNode<T>)
+		ValidateNewNode(node)
+		If Not head Then
+			CreateHead(head)
+		Else
+			InsertNodeBefore(head, node)
+			head = node
+		End If
+		node.list = Self
+	End Method
+	
+	Rem
+	bbdoc: Adds a new node containing the specified @value at the start of the #TLinkedList.
+	returns: The new node.
+	End Rem
+	Method AddFirst:TLinkedListNode<T>(value:T)
+		Local node:TLinkedListNode<T> = New TLinkedListNode<T>(Self, value)
+		If Not head Then
+			CreateHead(node)
+		Else
+			InsertNodeBefore(head, node)
+			head = node
+		End If
+		Return node
+	End Method
+	
+	Rem
+	bbdoc: Adds the specified new @node at the end of the #TLinkedList.
+	End Rem
+	Method AddLast(node:TLinkedListNode<T>)
+		ValidateNewNode(node)
+		
+		If Not head Then
+			CreateHead(node)
+		Else
+			InsertNodeBefore(head, node)
+		End If
+		node.list = Self
+	End Method
+	
+	Rem
+	bbdoc: Adds a new node containing the specified @value at the end of the #TLinkedList.
+	End Rem
+	Method AddLast:TLinkedListNode<T>(value:T)
+		Local node:TLinkedListNode<T> = New TLinkedListNode<T>(Self, value)
+		If Not head Then
+			CreateHead(node)
+		Else
+			InsertNodeBefore(head, node)
+		End If
+		Return node
+	End Method
+	
+	Rem
+	bbdoc: Removes all nodes from the #TLinkedList.
+	End Rem
+	Method Clear()
+		Local node:TLinkedListNode<T> = head
+		While node
+			Local tmp:TLinkedListNode<T> = node
+			node = node.nextNode
+			tmp.Clear()
+		Wend
+		
+		head = Null
+		size = 0
+	End Method
+	
+	Rem
+	bbdoc: Determines whether @value is in the #TLinkedList.
+	returns: #True if @value is in the #TLinkedList, or #Fale otherwise.
+	End Rem
+	Method Contains:Int(value:T)
+		Return Find(value) <> Null
+	End Method
+	
+	Rem
+	bbdoc: Finds the first node that contains @value.
+	returns: The first node that contains @value or #Null if not found.
+	End Rem
+	Method Find:TLinkedListNode<T>(value:T)
+		Local node:TLinkedListNode<T> = head
+		If node Then
+			Repeat
+				If node.value = value Then
+					Return node
+				End If
+				node = node.nextNode
+			Until node = head
+		End If
+		
+		Return Null
+	End Method
+	
+	Rem
+	bbdoc: Finds the last node that contains @value.
+	End Rem
+	Method FindLast:TLinkedListNode<T>(value:T)
+		If Not head Then
+			Return Null
+		End If
+		
+		Local last:TLinkedListNode<T> = head.previousNode
+		Local node:TLinkedListNode<T> = last
+		
+		If node
+			Repeat
+				If node.value = value Then
+					Return node
+				End If
+				node = node.previousNode
+			Until node = last
+		End If
+		
+		Return Null
+	End Method
+	
+	Rem
+	bbdoc: Removes the specified @node from the #TLinkedList.
+	End Rem
+	Method Remove(node:TLinkedListNode<T>)
+		ValidateNode(node)
+		RemoveNode(node)
+	End Method
+	
+	Rem
+	bbdoc: Removes the first occurrence of @value from the #TLinkedList.
+	End Rem
+	Method Remove:Int(value:T)
+		Local node:TLinkedListNode<T>
+		If node Then
+			RemoveNode(node)
+			Return True
+		End If
+		Return False
+	End Method
+	
+	Rem
+	bbdoc: Removes the node at the start of the #TLinkedList.
+	End Rem
+	Method RemoveFirst()
+		If Not head Then
+			Throw New TInvalidOperationException("list is empty")
+		End If
+		
+		RemoveNode(head)
+	End Method
+	
+	Rem
+	bbdoc: Removes the node at the end of the #TLinkedList.
+	End Rem
+	Method RemoveLast()
+		If Not head Then
+			Throw New TInvalidOperationException("list is empty")
+		End If
+		
+		RemoveNode(head.previousNode)		
+	End Method
+	
+Private
+	Method ValidateNode(node:TLinkedListNode<T>)
+		If Not node Then
+			Throw New TArgumentNullException("node")
+		End If
+		
+		If node.list <> Self Then
+			Throw New TInvalidOperationException("node parent list is different")
+		End If
+	End Method
+	
+	Method ValidateNewNode(node:TLinkedListNode<T>)
+		If Not node Then
+			Throw New TArgumentNullException("node")
+		End If
+		
+		If node.list Then
+			Throw New TInvalidOperationException("node is from another list")
+		End If
+	End Method
+	
+	Method RemoveNode(node:TLinkedListNode<T>)
+		If node.nextNode = node Then
+			head = Null
+		Else
+			node.nextNode.previousNode = node.previousNode
+			node.previousNode.nextNode = node.nextNode
+			If head = node Then
+				head = node.nextNode
+			End If
+			node.Clear()
+			size :- 1
+		End If
+	End Method
+	
+	Method CreateHead(node:TLinkedListNode<T>)
+		node.nextNode = node
+		node.previousNode = node
+		head = node
+		size :+ 1
+	End Method
+	
+	Method InsertNodeBefore(node:TLinkedListNode<T>, newNode:TLinkedListNode<T>)
+		newNode.nextNode = node
+		newNode.previousNode = node.previousNode
+		node.previousNode.nextNode = newNode
+		node.previousNode = newNode
+		size :+ 1
+	End Method
+Public
+
+End Type
+
+Rem
+bbdoc: Represents a node in a #TLinkedList.
+End Rem
+Type TLinkedListNode<T>
+Private
+	Field list:TLinkedList<T>
+	Field nextNode:TLinkedListNode<T>
+	Field previousNode:TLinkedListNode<T>
+Public
+	Field value:T
+
+	Rem
+	bbdoc: Creates a new #TLinkedListNode instance with the specified @value.
+	End Rem
+	Method New(value:T)
+		Self.value = value
+	End Method
+	
+Private
+	Method New(list:TLinkedList<T>, value:T)
+		Self.list = list
+		Self.value = value
+	End Method
+
+	Method Clear()
+		list = Null
+		nextNode = Null
+		previousNode = Null
+	End Method
+Public
+End Type
+
+Type TLinkedListIterator<T> Implements IIterator<T> 
+	Private
+	Field list:TLinkedList<T>
+	Field node:TLinkedListNode<T>
+	Field index:Int
+	Field value:T
+	
+	Method New(list:TLinkedList<T>)
+		Self.list = list
+		node = list.head
+	End Method
+	
+	Public
+
+	Method Current:T()
+		Return value
+	End Method
+	
+	Method MoveNext:Int()
+		If Not node Then
+			index = list.size + 1
+			Return False
+		End If
+		
+		index :+ 1
+		value = node.value
+		node = node.nextNode
+		If node = list.head Then
+			node = Null
+		End If
+		
+		Return True
+	End Method
+
+End Type