多维空间树 kd-tree

#lang scheme

( define ( make-node point axis left-child right-child )
   ( define ( dispatch msg . args )
      ( cond 
         [ ( eq? msg 'point ) point ]
         [ ( eq? msg 'axis ) axis ]
         [ ( eq? msg 'left-child ) left-child ]
         [ ( eq? msg 'right-child ) right-child ] ) )
   dispatch )

( define ( square-distance lst1 lst2 )
   ( cond
      [ ( null? lst1 ) 0 ]
      [ else 
        ( + ( expt ( - ( car lst1 )( car lst2 ) ) 2 )
            ( square-distance ( cdr lst1 )( cdr lst2 ) ) ) ] ) )

( define ( make-kd-tree )
   ( let ( [ root '() ] )
      ( define ( build-tree point-list )
         ( let ( [ point-vector ( list->vector point-list ) ] )
            ( define ( build point-vector depth )
               ( let* ( [ point-vector-length ( vector-length point-vector ) ]
                        [ median-index ( quotient point-vector-length 2 ) ] )
                  ( cond 
                     [ ( = point-vector-length 0 ) 'nil ]
                     [ else 
                       ( let* ( [ dimension ( length ( vector-ref point-vector 0 ) ) ]
                                [ axis ( modulo depth dimension ) ]
                                [ point-vector ( list->vector ( sort ( vector->list point-vector ) 
                                                #:key ( lambda ( item )( list-ref item axis ) ) < ) ) ] ) 
                          ( make-node ( vector-ref point-vector median-index )
                                      axis
                                      ( build ( vector-copy point-vector
                                              0
                                              median-index )
                                              ( + depth 1 ) )
                                      ( build ( vector-copy point-vector 
                                              ( + median-index 1 )
                                               point-vector-length )
                                              ( + depth 1 ) ) ) ) ] ) ) )
            ( set! root ( build point-vector 0 ) ) ) )
      ( define ( search-nearest query-point )
         ( let ( [ best-point ( make-hash ) ] )
            ( dict-set*! best-point "point" 'nil "distance" +inf.0 )
            ( define ( search this-node )
               ( cond 
                  [ ( eq? this-node 'nil )( void ) ]
                  [ else 
                    ( let* ( [ point ( this-node 'point ) ]
                             [ axis ( this-node 'axis ) ]
                             [ left-child ( this-node 'left-child ) ]
                             [ right-child ( this-node 'right-child ) ]
                             [ distance ( square-distance point query-point ) ]
                             [ axis-dimension-diff ( - ( list-ref query-point axis )
                                                       ( list-ref point axis ) ) ]
                             [ square-axis-dimension-diff ( * axis-dimension-diff 
                                                              axis-dimension-diff ) ] )
                       ( cond 
                          [ ( < distance ( dict-ref best-point "distance" ) )
                            ( dict-set! best-point "point" point )
                            ( dict-set! best-point "distance" distance ) ]
                          [ else ( void ) ] )
                       ( cond 
                          [ ( <= axis-dimension-diff 0 )
                            ( search left-child )
                            ( cond 
                               [ ( < square-axis-dimension-diff ( dict-ref best-point "distance" ) )
                                 ( search right-child ) ]
                               [ else ( void ) ] ) ]
                          [ else 
                            ( search right-child )
                            ( cond 
                               [ ( < square-axis-dimension-diff ( dict-ref best-point "distance" ) )
                                 ( search left-child ) ]
                               [ else ( void ) ] ) ] ) ) ] ) ) 
            ( search root )
            best-point ) )
      ( define ( dispatch msg . args )
         ( cond
            [ ( eq? msg 'build-tree )( build-tree ( car args ) ) ]
            [ ( eq? msg 'search-nearest )( search-nearest ( car args ) ) ] ) ) 
      dispatch ) )


( define tree ( make-kd-tree ) )
( tree 'build-tree '( ( 2 3 )( 5 4 )( 9 6 )( 4 7 )( 8 1 )( 7 2 ) ) )
( define res ( tree 'search-nearest '( 2.1 3.1 ) ) )
( sqrt ( dict-ref res "distance" ) )


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值