BinarySearchTrees.

BlitzMax Forums/BlitzMax Module Tweaks/BinarySearchTrees.

AntonyWells(Posted 2005) [#1]
Binary search trees allow you to store handles(Doubles for more precision) within a binary tree, then you can search for an exact entry very quickly( 100,000 elements can be searched in around 12-13 cycles in good cases, may vary based on data.). compared to 100,000 brute force/list wise)

whenever you insert something you get a node back.
When you use find it'll find an exact match or return null. FindApprox will find the closest double value to yours(Still using the fast method.) which is nicer for in game stuff.


rem
Strict

ModuleInfo "Version: 1.11"
ModuleInfo "Author:Antony Wells"
ModuleInfo "License:Open Source."
ModuleInfo "Copyright: Open Source."
ModuleInfo "Modserver: "
End Rem

Type BSTree
	
	Function Create:BSTree()
		Local Out:BSTree = New BSTree
			
		Return Out
	End Function
	
	Method Insert:BNode(Value:Double,Id:Int=0)
	
		If Root = Null
	
			Root = New BNode
			Root.Value = Value
			Root.Id = Id 
			Return Root
		Else
		
			Return Root.Insert( Value,Id)
	
		EndIf
	
	End Method
	
	Method FindNode:BNode( Value!)
		
		Return Root.FindNode( Value )
				
	End Method
	
	Method FindApprox:BNode( Value!)
		
		BNode.SmallV = 9999999999
	'	If BNode.SmallV<>99999999999999 Throw "Double precision not accurate enough for BST implentation"
		BNode.SmallN = Null 
		Return Root.FindApprox( Value )

	End Method
		
	Field Root:BNode
	
End Type

Type BNode 

	Method Insert:BNode( nValue:Double,Id:Int=0 )
		
		If nValue = Value Return
		If nValue<Value

			If Node[0] = Null
			
				Node[0] = New BNode
				Node[0].Top = BNode(Self)
				Node[0].Id = Id
				Node[0].Value = nValue
				Return Node[0]
			Else
			
				Node[0].Insert( nValue,Id )
			
			EndIf

		Else

			If Node[1] = Null
			
				Node[1] = New BNode
				Node[1].Id = Id
				Node[1].Top = BNode( Self )
				Node[1].Value = nValue
				Return Node[1] 
			Else 
			
				Node[1].Insert( nValue,Id )
				
			End If

		EndIf
		
	End Method

	Method FindNode:BNode( nValue:Double )
		If Value = nValue Return BNode(Self)
		If nValue<Value
			If Node[0] = Null Return Null
			Return Node[0].FindNode( nValue )
		Else
			If Node[1] = Null Return Null
			Return Node[1].FindNode( nValue )
		EndIf
	End Method

	Method FindApprox:BNode( nValue:Double )
		?debug
		BNode.Cycle:+1
		?
		Local dValue! = Abs(nValue-Value)
		
		If dValue<Bnode.SmallV
			
			Bnode.SmallV = dValue
			Bnode.SmallN = BNode( Self )
			
		EndIf
		
		If nValue = Value Return Bnode(Self)
		
		If nValue<Value
			
			If Node[0] = Null Return Bnode.SmallN
			Return Node[0].FindApprox( nValue )
			
		Else
			
			If Node[1] = Null Return Bnode.SmallN
			Return Node[1].FindApprox( nValue )
			
		EndIf
					
	End Method
	
	Field x:Double,y:Double,z:Double
	Global Cycle:Int
	Field Value!,Obj:Object,Id:Int
	Field Node:BNode[2],Top:BNode
	Global SmallV!,SmallN:BNode
End Type

Type BSVTree
	
	Method New()
		xTree = New BSTree
		yTree = New BSTree
		zTree = New BStree
	End Method
	
	Function Create( Verts:Double[] )
		Local Out:BSVTree = New BSVTree
		Local VertC:Int = Verts.Length()
		Local VertI:Int
		While VertI<VertC
			Out.xTree.Insert( Verts[ VertI],VertI/3)
			Out.yTree.Insert( Verts[ VertI+1],VertI/3)
			Out.zTree.Insert( Verts[ VertI+2],VertI/3)
			VertI:+3
		Wend
		Return Out
	End Function
	Method NearestVertex( X:Double,Y:Double,Z:Double )
		Local XNode:BNode = xTree.FindApprox( X )
		
	End Method
	Field xTree:BSTree,yTree:BSTree,zTree:BSTree
End Type




Private
Global FoldSpace = 80000
Function FoldPoint!( x!,y!,z!,Tune!=1)
	'x:*tune
	'y:*tune
	'z:*tune
	out! = (Foldspace*y+x)+(z*(Foldspace*Foldspace))
	Return out
End Function

Function UnfoldPoint( point:Double Var,x:Double Var,Y:Double Var,Z:Double Var,Tune!=1)
	y = point / foldSpace Mod foldSpace Mod foldSpace
'	x = point Mod FoldSpace Mod foldSpace
	z = point/(foldSpace*FoldSpace)
	x = point-y*foldSpace
End Function





Robert(Posted 2005) [#2]
There is a BRL.Map module which already does something very similar - only it works with objects instead of floats.


AntonyWells(Posted 2005) [#3]
Mark probably has a copy of Game programming data structures too.
Though findapprox is a new technique, which is most useful for in game stuff.(Where data is fuzzy..)


Bot Builder(Posted 2005) [#4]
Erm, yeah. Plus, I think you mean Longs not Doubles. Doubles are more precise floats. Longs are bigger ints. If you use doubles for pointers... sure, most of the time it'll round to the correct int... but not at a certain range away from 0.

Also, just because he implements that structure doesnt mean he has that book XD I've been planning on using this structure for a dictionary in an AI bot for like 2 years and havent heard of the book...


AntonyWells(Posted 2005) [#5]
Errm, no i don't.

The node returns has a obj handle for you to store an object. The value you pass is an indentifier for the node when searching.
Approx uses a distance (Maths) based approch, it does not round down to find the closest.

And I'm not saying he had the book, I'm saying he didn't invent the tecnique. Though i had no idea he had done it..it's not even in the docs ;)


Bot Builder(Posted 2005) [#6]
He does? erm, where? lol


AntonyWells(Posted 2005) [#7]
(Whispers into jacket coller) 'put a man on him.'