0

2d-tree

Bài toán 1: 2D-Tree

2D-Tree: cây 2 chiều với nhiều ứng dụng như: -Tìm điểm gần nhất : +Ứng dụng trong ggMap, định vị địa điểm gần bạn nhất -Tìm các điểm trong 1 phạm vi +Khoanh vùng phạm vi : lấy tất cả sản phẩm, phân tích phạm vi nào có nhiều người dùng để tập trung shipper vào khu vực đó ​

Quy tắc khi xây cây 2d-tree: -2 con của node dọc là ngang và ngược lại -Khi chèn 1 node vào cây, khi đi qua node : +Level lẻ: so sánh hoành độ, nhỏ hơn => trái , lớn hơn hoặc bằng => phải +Level chẵn so sánh tung độ, nhỏ hơn => trái ( dưới khi vẽ trên lưới ) , lớn hơn hoặc bằng=> phải (trên khi vẽ trên lưới ) +Sửa bounding rect của node vừa thêm dựa vào bounding rect của cha :

Insert node

-Recursive : 
class Node {
    Point2D point 
    Node left 
    Node right
    boolean isVertical
    Rect bounding
}
function Node insert(cur : node, point : point2D, bounding :Rect, isVertical){
    if(cur == null){ return new Node (point, bounding)} 
    if(cur.isVertical){
        if(cur.point().x() > point.x()){
            Rect newBounding = { ...bounding, maxX: cur.point().x()}
            cur.setLeft(cur.left, point, newBounding, !cur.isVertical)
        }
        else{
         Rect newBounding = { ...bounding, minX: cur.point().x()}
           cur.setRight(cur.right, point, newBounding, !cur.isVertical)
        }
    }
    else{
          if(cur.point().y() > point.y()){
            Rect newBounding = { ...bounding, maxY: cur.point().y()}
            cur.setLeft(cur.left, point, newBounding, !cur.isVertical)
        }
        else{
         Rect newBounding = { ...bounding, minY: cur.point().y()}
           cur.setRight(cur.right, point, newBounding, !cur.isVertical)
        }
    }
    return cur
}

**Ví dụ: xây cây 2d-trêe và vẽ trên lưới ** image.png =>Cây 2d-tree : image.png =>Lưới : image.png =>Hộp bao :

   *Bounding rect của 1 điểm sẽ là hcn phạm vi của node đó thường được kế thừa từ cha và chỉnh sửa tại phần x / y mà thằng con nằm bên trái / phải so với cha . 
   Ví dụ : A(2,3) có bounding rect [-&, &] x [-& , &] 
               => B(3,5) nằm bên phải A => bounding rect : [2, +&] x [-& , +&]
               & : vô cùng

image.png Tư tưởng thuật toán tìm kiếm theo vùng rect:

 -Đi từ gốc, tại mỗi điểm check bounding rect của điểm đó có intersect với target rect hay không : 
   + Nếu CÓ check node đó có thuộc rect hay không và đi sang cả 2 bên trái và phải của phần đó.
   + Nếu KO tỉa nhánh đó đi (bỏ luôn vì phạm vi của cha đã ko thuộc rồi thì cần gì mất công check phạm vi của node con ~ chắc chắc cũng là không thuộc ~)
-Code : 
function f(root, targetRect ) //BFS 
   -res:List
   -tracks:Queue
   -tracks.add(root)
   while(!tracks.isEmpty () ){
   cur = tracks.pool()
   if(cur == null) continue;
   if(!intersect (targetRect , cur.boundingRect)){
       continue;
   }
   if(targetRect.contains(cur)){
       res.add(cur)
   }
     tracks.add(cur.left)
   tracks.add(cur.right)
   }
   return res;

function recursion (cur, targetRect, res) //DFS 
  if(cur == null) continue;
   if(!intersect (targetRect , cur.boundingRect)){
       continue;
   }
   if(targetRect.contains(cur)){
       res.add(cur)
   }
     tracks.add(cur.left,...)
   tracks.add(cur.right,...)
   }

Độ phức tạp

    -Worst: đi hết cây: N 
    -Average: logN 

Với hình chữ nhật được cho dưới đây, hãy đánh số các nút (không rỗng) theo thứ tự mà chúng được truy cập bởi một truy vấn theo vùng (range query). Những cây con nào bị tỉa (pruned)? (Lưu ý: Một số cây con rỗng có thể bị tỉa, và một số thì không.)

image.png

Bounding rect của các điểm image.png

-Thứ tự nút được truy cập theo DFS 
+1: A intersect: tracks gọi   B, E 
+2: B : intersect : gọi B.left (null) và C  
+3:C : intersect : gọi left(D) và F 
+ 4:D : intersect : gọi left (null) và right(null)
+5 :F : not intersect => prune (tỉa luôn ~ return) 
+6:E : intersect : gọi G 
+7:G intersect . 

Bài toán 2: Nearest Neighbour Search

Input: You had a set of 2d points which present the location of stores Output: Let's build a effective data structure to store this set to satisfy search requirement that determines the nearest store to any client's location (x,y) -Use above approach that we installed to build 2dTree Strategy: ```js -Check bestPoint.distanceSquaredTo(queryPoint) < cur.bounding.distanceSquaredTo(queryPoint) => prune : return because -Compare the distance bestPoint and queryPoint to the distance cur.point and queryPoint at every turn call recursive +Cur.isVertical : compare cur.x() to queryPoint.x() +Else : compare cur.y() to queryPoint.y() =>Navigate to one side : left / right -However,need to compare h(queryPoint, cur.point()) to bestPoint.distance : (~vertical : h = abs( cur.point().x() - queryPoint.x()) ~else : h = ...y )

       _ h < bestPoint.distanceSquaredTo(queryPoint) => navigate rest branch because it may contain nearer point 
 -Code 
 function Point nearnest (cur :Node, queryPoint : Point2D, bestPoint: Point2D) {
 if(cur == null) return bestPoint;
 if(
 
 }
Node first , second 
 -if(cur.isVertical()){
             
 }
-if(cur.point().distanceSquaredTo(queryPoint)) < bestPoint.distanceSquaredTo(queryPoint)) => bestPoint = cur.point() 

if(cur.isVertial
```

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí