Implementation:Segment Tree 线段树

早就听人提起过线段树,今天有题搞不出来,讨论上说要用一下线段树,看了下,本质上是空间划分索引,只不过是一维上面的,如果在二维则是四叉树,三维则是八叉树,如果可以动态调整那么跟R-Tree就很相似了,他们都可以对范围查询做出响应。参照书上写了一个,虽然不多,但是渣渣也写的很是费力

#include <iostream>

#include <cstdlib>

#include <vector>



using namespace std;



class SegmentTree {

    private:

        int *mem;

        int capacity;

        int storage_size;

    private:

        void init_level_update() {

            int k = capacity - 1;

            while (--k >= 0) {

                int L = (k<<1) + 1;

                int R = L + 1;

                mem[k]= min(mem[L], mem[R]);

            }

        }



        int query(int a, int b, int idx, int L, int R) {

            if (b <= L || a >= R) return INT_MAX;

            if (a <= L && R <= b) return mem[idx];



            int ml = query(a, b, (idx<<1) + 1, L, (L+R)/2);

            int mr = query(a, b, (idx<<1) + 2, (L+R)/2, R);

            return min(ml, mr);

        }

        

        void init_mem(int _capacity) {

            if (_capacity <= 0) {

                capacity = 0;

                return;

            }

            int n = 1;

            while (n < _capacity) n<<=1;

            capacity = n;

            storage_size = capacity * 2 - 1;

            mem = new int[storage_size];



            int k = 0;

            while (k < storage_size) mem[k++] = INT_MAX;

        }

    public:

        SegmentTree(int _capacity) {

            init_mem(_capacity);

        }

        SegmentTree(vector<int>::iterator begin, vector<int>::iterator end) {

            capacity = end - begin;

            init_mem(capacity);



            int k = capacity - 1;

            vector<int>::iterator iter = begin;

            while (iter != end) mem[k++] = *iter++;



            init_level_update();

        }

        ~SegmentTree() {

            delete[] mem;

        }

        

        // update value in original data index

        void update(int idx, int val) {

            if (idx >= capacity || idx < 0) return;

            int k = idx + capacity - 1; // internal storage index

            mem[k] = val;

            while (k > 0) {

                k = (k - 1) >> 1;

                int L = (k << 1) + 1;

                int R = L + 1;

                mem[k] = min (mem[L], mem[R]);

            }

        }

        

        // retrive the min value in index range [a, b)

        int query(int a, int b) {

            return query(a, b, 0, 0, capacity);

        }

        

        void print_mem(const char* msg) {

            cout<<msg<<endl;

            for (int i=0; i<(capacity*2-1); i++) {

                cout<<mem[i]<<" ";

            }

            cout<<endl;

        }

};





void test(const char* msg, SegmentTree& seg_tree, int* data, int size) {

    cout<<msg<<endl;

    for (int i=0; i<=size; i++) {

        for (int j=i+1; j<=size; j++) {

            int tmin = seg_tree.query(i, j);

            cout<<"min of ("<<i<<","<<j<<") = "<<tmin<<endl;

            int amin = INT_MAX;

            for (int k=i; k<j; k++) if (data[k] < amin) amin = data[k];

            if (amin != tmin)

                cout<<"fail"<<endl;

            else

                cout<<"ok"<<endl;

        }

    }

}

int main() {

    int h[] = {6, 2, 5, 4, 5, 3, 6};

    int size= sizeof(h) / sizeof(int);

    vector<int> hs(h, h + size);

    

    SegmentTree seg_tree(hs.begin(), hs.end());

    test("Test construction with data :", seg_tree, h, size);

    

    SegmentTree init_empty_tree(size);

    for (int i=0; i<size; i++) init_empty_tree.update(i, h[i]);

    test("Test construction without data", init_empty_tree, h, size);

    

    system("pause");

    return 0;

}

 下面是一个带有返回最小值索引值的改进版本

class SegmentTree {

    private:

        int *mem;

        int *idx;

        int capacity;

        int storage_size;



    private:

        void init_level_update() {

            int k = capacity - 1;

            while (--k >= 0) {

                int L = (k<<1) + 1;

                int R = L + 1;

                if (mem[L] < mem[R]) {

                    mem[k] = mem[L];

                    idx[k] = idx[L];

                } else {

                    mem[k] = mem[R];

                    idx[k] = idx[R];

                }

            }

        }



        pair<int, int> query(int a, int b, int idx, int L, int R) {

            if (b <= L || a >= R) return make_pair(INT_MAX, -1);

            if (a <= L && R <= b) return make_pair(mem[idx], this->idx[idx]);



            pair<int, int> ml = query(a, b, (idx<<1) + 1, L, (L+R)/2);

            pair<int, int> mr = query(a, b, (idx<<1) + 2, (L+R)/2, R);

            return ml.first < mr.first ? ml : mr;

        }



        void init_mem(int _capacity) {

            if (_capacity <= 0) {

                capacity = 0;

                return;

            }

            int n = 1;

            while (n < _capacity) n<<=1;

            capacity = n;

            storage_size = capacity * 2 - 1;

            mem = new int[storage_size];

            idx = new int[storage_size];

            

            int k = 0;

            while (k < storage_size) mem[k++] = INT_MAX;

            k = capacity - 1;

            int i = 0;

            while (k < storage_size) idx[k++] = i++;

        }

    public:

        SegmentTree(int _capacity) {

            init_mem(_capacity);

        }

        SegmentTree(vector<int>::iterator begin, vector<int>::iterator end) {

            capacity = end - begin;

            init_mem(capacity);



            int k = capacity - 1;

            vector<int>::iterator iter = begin;

            while (iter != end) mem[k++] = *iter++;



            init_level_update();

        }



        ~SegmentTree() {

            delete[] mem;

            delete[] idx;

        }



        // update value in original data index

        void update(int index, int val) {

            if (index >= capacity || idx < 0) return;

            int k = index + capacity - 1; // internal storage index

            mem[k] = val;

            while (k > 0) {

                k = (k - 1) >> 1;

                int L = (k << 1) + 1;

                int R = L + 1;

                if (mem[L] < mem[R]) {

                    mem[k] = mem[L];

                    idx[k] = idx[L];

                } else {

                    mem[k] = mem[R];

                    idx[k] = idx[R];

                }

            }

        }



        // retrive the min value in index range [a, b)

        pair<int, int> query(int a, int b) {

            return query(a, b, 0, 0, capacity);

        }



        void print_mem(const char* msg) {

            cout<<msg<<endl;

            for (int i=0; i<(capacity*2-1); i++) {

                cout<<mem[i]<<" ";

            }

            

            for (int i=0; i<capacity * 2 - 1; i++) {

                cout<<idx[i]<<",";

            }

            cout<<endl;

        }

};
View Code

 

参考:

  挑战程序设计竞赛第二版

你可能感兴趣的:(tree)