2015-08-31 36 views
5

Hiện tại tôi đang triển khai BST trong Java cho dự án đại học của mình. Như chúng ta đã biết, BST khá tốt khi tìm kiếm một đơn vị đơn là O (log n) trong một cây cân bằng.Lấy khoảng thời gian của cây tìm kiếm nhị phân nhanh như mảng đã sắp xếp

Nhưng cách thực hiện tìm kiếm giữa giá trị ab? (Một < b)

Hãy nói rằng tôi có cây này

│    ┌── 125 
│   ┌── 122 
│   │ └── 120 
│  ┌── 117 
│  │ │ ┌── 113 
│  │ └── 112 
│  │  └── 108 
│ ┌── 86 
│ │ │ ┌── 85 
│ │ └── 72 
└── 59 
    │   ┌── 56 
    │  ┌── 52 
    │ ┌── 47 
    │ │ │ ┌── 43 
    │ │ └── 39 
    │ │  │ ┌── 38 
    │ │  └── 36 
    └── 28 
     │  ┌── 18 
     │ ┌── 15 
     └── 2 
      └── 1 

Tôi muốn tạo ra một phương pháp range(a,b) trở về giá trị giữa ab toàn diện. (Lưu ý: ab là không cần thiết trong cây!)

Ví dụ: range(53,112) sẽ trở lại 56,59,72,85,86,108,112

Đây là mã giả của tôi

/* recursive method */ 
range(a,b) 
    range(a,b,root); 

/* helper method */ 
range(a,b,node) 
    if (a <= node.value <= b) 
     if (node.left != null) and (node.value != a) 
      range(a,b,node.left) 

     print node.value 

     if (node.right != null) and (node.value != b) 
      range(a,b,node.right) 

    else if node.value < a 
     if (node.right != null) 
      range(a,b,node.right) 

    else // node.value > b 
     if (node.left != null) 
      range(a,b,node.left) 

Nhưng tôi nghĩ rằng phương pháp của tôi là chậm hơn.

Ví dụ: trong một mảng được sắp xếp, chúng tôi phải thực hiện tìm kiếm nhị phân trên ab và nhận chỉ mục tương ứng của chúng. Sau đó, chúng tôi lặp lại từ chỉ mục của a thành chỉ mục của b.

Có đúng là BST sẽ thực hiện chậm hơn trong việc tìm kiếm nhiều giá trị không? Có thể cải thiện thuật toán của tôi nhanh như một mảng được sắp xếp không?

Trả lời

0

Tùy thuộc vào cách bạn có thể trả lại kết quả, một mảng được sắp xếp có thể có lợi thế rất lớn là không cần sao chép kết quả ở bất kỳ đâu. Chỉ cần trở về một con trỏ + chiều dài xem vào mảng là nhanh hơn và thân thiện với bộ nhớ cache hơn làm cho một bản sao của phạm vi vào bộ đệm khác. Một cây luôn luôn phải sao chép các yếu tố ra khỏi cây. Ngay cả khi bạn cần một bản sao (để sửa đổi hoặc bất cứ điều gì), memcpy là nhanh hơn nhiều so với đi bộ một cây.

Đây không phải là vấn đề nếu bạn có thể xử lý khi đang di chuyển trong khi đi bộ (như bạn đang làm với print).

Tôi luôn có vẻ viết câu trả lời trước khi googling. Nó chỉ ra rằng trees to answer range queries are a thing. Dường như nó thường được thực hiện cho các phạm vi 2D hoặc 3D (ví dụ, mỗi điểm có tọa độ x và y), mà bạn không thể làm với một mảng được sắp xếp. Tôi cho rằng điều này là bởi vì mặc dù nó hiệu quả nhất có thể, nhưng nó không hiệu quả như trả lại một cửa sổ chiều dài con trỏ thành một mảng được sắp xếp!

Tôi sẽ không để sao chép/dán toàn bộ thuật toán từ wikipedia, chỉ là ý tưởng thông minh:

Để báo cáo những điểm nằm trong khoảng [x1, x2], chúng tôi bắt đầu bằng cách tìm kiếm cho x1 và x2. Tại một số đỉnh trong cây, các con đường tìm kiếm để x1 và x2 sẽ phân ra

Đây là cách bạn có hiệu quả phát hiện toàn bộ subtrees mà bạn biết sẽ nằm trong phạm vi của bạn, xem wikipedia và/hoặc google "cây truy vấn phạm vi "cho nhiều chi tiết.


Quan sát trước googling của tôi là bạn có thể tránh so sánh và chỉ cần đi bộ một số subtrees. Trong ví dụ của bạn, cây con trái của 86 được đảm bảo cho tất cả nằm trong phạm vi, bởi vì chúng tôi biết tất cả chúng đều là> 59 và < 86, được gắn chặt hơn [a..b]. Tôi đã không nghĩ ra một cách để tìm kiếm trường hợp đặc biệt này mà sẽ không tốn nhiều chi phí hơn là nó được cứu.

Các vấn đề liên quan