[演算法]線段樹(IntervalTree)

來源:互聯網
上載者:User

標籤:

   轉載請註明出處:http://www.cnblogs.com/StartoverX/p/4617963.html 

  線段樹是一顆二叉搜尋樹,線段樹將一個區間劃分成一些單元區間,每一個區間對應線段樹的一個分葉節點。對於線段樹的每一個非葉子節點[a,b],它的左兒子表示的區間為[a,(a+b)/2],右兒子表示的區間為[(a+b)/2+1,b]。因此線段樹是平衡二叉樹,最後的子節點數目為N,即整個線段區間的長度。

                                                                             

     線段樹的特徵:

  1.線段樹的長度不超過logL(L是最長區間的長度)。

  2.線段樹把區間上的任意一條線段都分成不超過2logL條線段。

  這些結論為線段樹能夠在O(logL)時間內完成一條線段的插入,刪除,尋找等工作,提供了理論依據。

    線段樹的用途:

  線段樹適用於和區間統計有關的問題。比如某些資料可以按區間進行劃分,按區間動態進行修改,而且還需要按區間多次進行查詢,那麼使用線段樹可以達到較快查詢速度。

 資料結構:  

typedef struct IntervalTree{    int right;    int left;    IntervalTree* right_child;    IntervalTree* left_child;    /*other information*/
//通常為瞭解題需要記錄其他的資訊。
}IntervalTree;

    線上段上建樹:

IntervalTree* buildTree(int a,int b){    IntervalTree* tree = new IntervalTree;    tree->right = b;    tree->left = a;    tree->right_child = NULL;    tree->left_child = NULL;    if(b > a)    {      int mid = (a + b)/2;      tree->right_child = buildTree(mid+1,b);      tree->left_child = buildTree(a,mid);    }    return tree;}//通常線段上會記錄其他的資訊,需要在建樹時同時記錄到樹的每一個node。 

 

線段樹通常引入為了解決關於區間的問題,在樹中插入線段,刪除線段,查詢線段的方法都和具體問題有關,我們以下面的問題為例: 

已知範圍A1....An,在該範圍內不斷進行插入新線段(Ai...Aj,1<=i<=j<=n),刪除線段(Ai...Aj,1<=i<=j<=n)的操作,最後求某個線段被覆蓋的次數?

 

為瞭解決這個問題,我們線上段A1...An上建樹,並且線上段樹中儲存被覆蓋的次數cover。

 

資料結構:  

typedef struct IntervalTree{    int right;    int left;    int cover;//儲存被覆蓋的次數。    IntervalTree* right_child;    IntervalTree* left_child;}IntervalTree;

 

建樹:

IntervalTree* buildTree(int a,int b){    IntervalTree* tree = new IntervalTree;    tree->right = b;    tree->left = a;    tree->cover = 0;//初始時cover為0    tree->right_child = NULL;    tree->left_child = NULL;    if(b > a)    {      int mid = (a + b)/2;      tree->right_child = buildTree(mid+1,b);      tree->left_child = buildTree(a,mid);    }    return tree;}

 

插入新線段:

void insert(int a,int b,IntervalTree* tree){    if(tree->right == b && tree->left == a)    {        tree->cover++;        return;    }    int mid = (tree->left + tree->right)/2;    if(a > mid)    {        insert(a,b,tree->right_child);    }    else if(b <= mid)    {        insert(a,b,tree->left_child);        }    else    {        insert(a,mid,tree->left_child);        insert(mid+1,b,tree->right_child);    }}

 

刪除線段:

void delete_interval(int a,int b,IntervalTree* tree){    if(tree->right == b && tree->left == a)    {        tree->cover--;        return;    }    int mid = (tree->left + tree->right)/2;    if(a > mid)    {        delete_interval(a,b,tree->right_child);    }    else if(b <= mid)    {        delete_interval(a,b,tree->left_child);    }    else    {        delete_interval(a,mid,tree->left_child);        delete_interval(mid+1,b,tree->right_child);    }}

 

查詢線段覆蓋次數:

int query(int a,int b,IntervalTree* tree){    if(tree->right == b && tree->left == a)    {        return tree->cover;    }    int mid = (tree->right + tree->left)/2;    if(a > mid)    {        return tree->cover + query(a,b,tree->right_child);    }    else if(b <= mid)    {        return tree->cover + query(a,b,tree->left_child);    }    else    {        int cover_right = query(mid+1,b,tree->right_child);        int cover_left = query(a,mid,tree->left_child);        return tree->cover + ((cover_right > cover_left) ? cover_right : cover_left);    }}

 

線段樹應用舉例:POJ 3264:Balanced Lineup:http://www.cnblogs.com/StartoverX/p/4618041.html

 

[演算法]線段樹(IntervalTree)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.