zoukankan      html  css  js  c++  java
  • 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

    参考:

      挑战程序设计竞赛第二版

  • 相关阅读:
    进程与线程
    闭包
    form表单提交
    让图片在div盒子中水平垂直居中
    第一个shell脚本——修改配置文件
    Linux系统find命令的常用方法
    Linux使echo命令输出结果带颜色
    Linux面试题
    无人值守批量安装
    Linux系统PXE高效批量网络装机的配置
  • 原文地址:https://www.cnblogs.com/lailailai/p/3664650.html
Copyright © 2011-2022 走看看