SML-Rangelab

Rangelab

实验背景

为实现范围查找,设计orderTable数据结构,本实验实现了一些基本的接口,并实现一定条件下的Rane query

实验细节

1 Ordered Tables

1.1 First and last

fun first (T : 'a table) : (key * 'a) option
fun last (T : 'a table) : (key * 'a) option

函数功能:

返回ordered table的第一个或者最后一个元素

函数思路:

既为BST存储,那么根据BST的特性求最大最小元素即可

函数代码:

  fun first (T : 'a table) : (key * 'a) option =
    case Tree.expose T of
      NONE => NONE
      | SOME {key, value, left, right} =>
        case (Tree.expose left,Tree.expose right)
          of (NONE,_) => SOME (key,value)
           | (_,_) => first left

  fun last (T : 'a table) : (key * 'a) option =
    case Tree.expose T of
      NONE => NONE
      | SOME {key, value, left, right} =>
        case (Tree.expose left,Tree.expose right)
          of (_,NONE) => SOME (key,value)
           | (_,_) => last right
1.2 Previous and next

fun previous (T : 'a table) (k : key) : (key * 'a) option
fun next (T : 'a table) (k : key) : (key * 'a) option

函数功能:

返回给定元素的之前或者之后的一个元素

函数思路:

将所给orderedtable在所给的key处切开,产生左树和右树,对左树取last即为previous,对右树取first即为next

函数代码:

  fun previous (T : 'a table) (k : key) : (key * 'a) option = 
    last (#1 (Tree.splitAt (T,k)))

  fun next (T : 'a table) (k : key) : (key * 'a) option =
    first (#3 (Tree.splitAt (T,k)))

1.3  Join and split

fun join (L : 'a table, R : 'a table) :'a table

ffun split (L : 'a table, k : key) :'a table * 'a option * 'a table

函数功能:

合并两个table或者在某点切开一个table

函数思路:

调用Tree.join以及Tree.splitAt 即可

函数代码:

  fun join (L : 'a table, R : 'a table) : 'a table =
    Tree.join (L,R)

  fun split (T : 'a table, k : key) : 'a table * 'a option * 'a table =
    Tree.splitAt (T,k)

1.4 getRange

fun getRange (T : 'a table) (low :key, high :key) : 'a table

函数功能:

返回位于给定的key:low和high之间的元素构成的新的table

函数思路:

分别在low和high处切开,再取中间元素合并即可

函数代码:

  fun getRange (T : 'a table) (low : key, high : key) : 'a table =
    let
      val (_,x,r) = split (T,low)
      val x' = case x 
        of NONE => r
         | SOME v => join (Tree.singleton (low,v),r) 
      val (l,y,_) = split (x',high)
      val y' = case y 
        of NONE => l
         | SOME v => join (Tree.singleton (high,v),l)
    in
      y'
    end


2 Range Query

2.1 makeCountTable

fun makeCountTable:point seq -> countTable

函数功能:

将所给的点串转化成countable

函数思路:

将输入的点按横坐标从小到大排序,然后整理成一个Table,Table.value是x<=key的全部点所构成的Table

函数代码:

  type countTable = ((point seq) table) table
  
  fun makeCountTable (S : point seq) : countTable =
    if Seq.length S = 0 then empty ()
    else
    let
      val preS = Seq.map (fn (x,y) => (x,(y,(x,y)))) S
      val preT = Seq.map (fn (x,y) => (x,collect y)) (Seq.collect (fn (x,y) => compareKey (x,y)) preS)
      fun f (x:(Key.t * Key.t) seq,y:(Key.t * Key.t) seq) = Seq.append (x,y)
      val res = Seq.scani (fn ((m,x),(n,y)) => (n,merge f (x,y))) (#1 (Seq.nth preT 0),empty ()) preT
    in
      fromSeq res
    end
渐进复杂度分析:

W(map)=O(n) S(map)=O(1)

W(preT)=O(nlogn) S(preT)=O(log^2n)

W(res)=O(n) S=O(logn)

2.2 count

count:Table -> point * point -> int

函数功能:

返回给定点所确定的矩形区域内的点的个数

函数思路:

求出xLight之前的点数以及xRight之前的点数作差即可

函数代码:

  fun count (T : countTable)
                   ((xLeft, yHi) : point, (xRght, yLo) : point) : int  =
    if size T = 0 then 0
    else
    let
      val left = previous T xLeft 
      val leftNum = case left of NONE => 0 
                               | SOME x => size (getRange (#2 x) (yLo,yHi))
      val right = case find T xRght of NONE => previous T xRght
                                     | SOME x => SOME (xRght,x)
      val rightNum = case right of NONE => 0 
                               | SOME x => size (getRange (#2 x) (yLo,yHi))
    in
      rightNum - leftNum
    end





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值