درخت بازه‌ها

در علوم کامپیوتر، از ساختمان داده درخت بازه‌ها برای ذخیره‌کردن بازه‌ها استفاده می‌شود. این ساختمان‌داده امکان یافتن بازه مربوط به یک نقطه داده شده را فراهم می‌کند. می‌توان هر گره از درخت در با پیچیدگی زمانی (o (log n تغییر داد.
در مورد درخت‌ها
درخت‌ها قسمت بزرگی از داده‌ساختارهای علم کامپیوتر را پوشش می‌دهند. درخت در حالت کلی به گراف هم‌بندی گفته می‌شود که دور ندارد.
درخت ریشه‌دار درختی است، که در آن بین راس‌ها رابطه پدر و فرزندی وجود دارد (ساختاری شبیه شجره‌نامه دارد).
ساختار درخت بازه‌ها
230px
درخت بازه‌ها، درختی ریشه‌دار است که هر راس غیر برگ آن دقیقا دو فرزند دارد. در این درخت هر راس نشان‌دهنده یک بازه است.
برگ‌ها در این درخت نشان‌دهنده بازه‌هایی به طول یک هستند. رئوس غیر برگ همگی دو فرزند دارند؛ اگر بازه نسبت‌داده‌شده به فرزندان چپ و راست به ترتیب و باشد، بازه این راس است. طول بازه نسبت‌داده‌شده به هر راس توانی از ۲ است (در صورتی که تعداد برگ‌ها توانی از ۲ باشد).
در نتیجه اگر راسی نشان‌دهنده بازه باشد؛ فرزند سمت چپ نشان دهنده بازه و فرزند راست نشان‌دهنده بازه است.
این درخت اغلب در مورد سوال‌هایی به کار می‌رود که عملیاتی روی بازه‌ها انجام می‌شود یا در هر مرحله به ما دستوری می‌دهند و باید تصمیم درست را در هر مرحله بگیریم.
تحلیل زمانی
اردر همه کارها در این داده‌ساختار ( است که طول بازه‌ای است که ریشه نشان می‌دهد. چرا که اگر در حال جستجوی بازه ، در راس x باشیم (x نماینده بازه است)؛
۱- اگر p برابر P و q برابر Q باشد بازه پیدا شده و عمل مورد نظر را انجام بده (پایان جستجو).
۲- اگر بازه مورد نظر با هر دو فرزند تداخل داشت: به دنبال در و در بگرد.
۳- اگر بازه مورد نظر فقط با یکی از فرزندان تداخل داشت: به دنبال در فرزند مذکور بگرد.
به نظر می‌رسد ممکن است حالت دوم تکرار شود و تمام رئوس را پیمایش کنیم، در صورتی که به سادگی می‌توان دریافت اگر یک بار حالت دوم رخ دهد (هر دو فرزند را پیمایش کنیم) آنگاه در هیچ مرحله دیگری لازم نیست هر دو انتهای بازه را بررسی کنیم. چرا که از یک طرف بازه ما به ابتدا یا انتها چسبیده و اگر دو قسمت را بررسی کنیم یکی از دو قسمت درجا به شرط پایان می‌رسد.
پیاده‌سازی با ++C
void find(int p,int q,node x,int P,int Q){
if(pP -- qQ){
//found and do the query
return;
int mid=(P+Q)/2;
if(q =mid){
find(p,q,x.right,mid,Q);
else{
find(p,mid,x.left,P,mid);
find(mid,q,x.right,mid,Q);
و این هم یک کد ساده که دو عمل تبدیل تمامی اعداد یک بازه به یک عدد و پیدا کردن بزرگترین عدد یک بازه را پشتیبانی میکند.
const int N = 1000 * 100 + 5;
class segment{
int v4*N, P4*N, Q4*N, mrk4*N;
public:
void build(int x,int p,int q){
Px = p, Qx = q;
if(p == q) return ;
int m = (p + q)>> 1;
build(x <<1,p,m);
build((x <<1) + 1,m + 1,q);
inline void mpas(int x){
if(mrkx){
mrkx = 0;
if(Px == Qx) return ;
mrkx <<1 = mrk(x <<1) + 1 = 1;
vx <<1 = v(x <<1) + 1 = vx;
void change(int x,int p,int q,int val){
mpas(x);
if(p <= Px -- Qx <= q){
mrkx = 1;
vx = val;
return ;
if(Qx q)
return ;
change(x <<1,p,q,val);
change((x <<1) + 1,p,q,val);
vx = max(vx <<1,v(x <<1) + 1);
int find_max(int x,int p,int q){
mpas(x);
if(p <= Px -- Qx <= q)
return vx;
if(Qx q)
return -INF;
return max(find_max(x <<1,p,q), find_max((x <<1) + 1,p,q) );
درخت‌های بازه‌ای دوبعدی نیز وجود دارند. یعنی بازه‌های یک بعدی تبدیل به یک زیر مستطیل می‌شوند. در این حالت هر راس نشان‌دهنده یک مستطیل است که طول و عرض آن توانی از دو است. در حالت کلی می‌توان گفت درخت بازه‌ای دوبعدی یک درخت بازه‌ای معمولی است که هر راس آن ریشه یک درخت بازه‌ای است و هر راس دو پدر دارد.
نوع دیگری درخت بازه‌ای به نام درخت فنویک هم وجود دارد.
Segment Tree
راس‌هایی که درجه آن‌ها یک است، برگ نامیده می‌شوند.
Fenwick Tree