zoukankan      html  css  js  c++  java
  • 基数树

    原理参考《算法导论》

    注:代码设定,支持索引的位数最大是32位,当然可以修改让其支持64和32位的索引

    首先定义一些常量(修改此处的常量,让其支持64位的索引)

    #define MAX_BITS 0x80000000 
    #define INT_BITS 32  //32位下的int

    然后定义一个基数树类

    template <typename T, int bits, int height>//bits代表索引的位数,height代表高度, 暂时支持32位
    class radix_tree {
    public:
        struct _Nodetype;
        typedef union _Autotype {
            _Nodetype *DeepNodes;//下一层
            T *slots;
        }Autotype;
        typedef struct _Nodetype {
            _Nodetype() { autov.DeepNodes = NULL; }
            _Nodetype(_Nodetype *node) { autov.DeepNodes = node; }
            _Nodetype(T *s) { autov.slots = s; }
            Autotype autov;
        }Nodetype, *pNodetype;
        radix_tree() {
            root = new Nodetype((pNodetype)NULL);
        }
        ~radix_tree() {
            
        }
        void radix_insert(int index, T key);//T类型应用时是指针,指向对象
        T radix_search(int index);
        void radix_delete(int index);//惰性删除
        void radix_empty();//未实现,建议采用双线程池,这样方便这个函数回收内存
    private:
        int radix_mask(int h);
        int radix_index(const int index, int h);
        pNodetype root;
    };

    关于类成员实现

    radix_mask成员负责根据所在树的层数,动态生成掩码。比如本例中使用18位的索引值,然后定义树高为3,那么在第一层的掩码是0x3F000,第二层的掩码是0xFC0,第三层的掩码是0x3F

    template <typename T, int bits, int height>
    int radix_tree<T, bits, height>::radix_mask(int h) {//1到height层
        int slotbits = bits / height, skipbits = INT_BITS - bits + (h - 1)*slotbits, tMask = 0;
        if (h<1 || h>height) return -1;
        while (skipbits < INT_BITS - bits + slotbits*h) {
            tMask |= (MAX_BITS >> skipbits);
            skipbits++;
        }
        return tMask;
    }

    radix_index成员负责提取索引中的偏移值。比如18位索引,第一层的时候,掩码为0x3F000,那么通过此掩码提取出来的6位偏移值,用于查找第一层的查找。其余层数以此类推。

    template <typename T, int bits, int height>
    int radix_tree<T, bits, height>::radix_index(const int index, int h) {
        int slotbits = bits / height, lowerMask = radix_mask(height), mask;
        if (h<1 || h>height) return -1;
        mask = radix_mask(h);//更新mask
        return (index & mask) >> (bits / height*(height - h)) & lowerMask;
    }

    radix_insert成员通过提供的索引值,插入到指定位置

    template <typename T, int bits, int height>
    void radix_tree<T, bits, height>::radix_insert(int index, T key) {
        pNodetype node = root;
        for (int tree_h = 1; tree_h < height; tree_h++) {//目录,没有数据
            if (node->autov.DeepNodes == NULL)
                node->autov.DeepNodes = new Nodetype[pow(2, bits / height)];
            node = &node->autov.DeepNodes[radix_index(index, tree_h)];
        }
        //录入数据
        if (node->autov.slots==NULL)
            node->autov.slots = new T[pow(2, bits / height)];
        node->autov.slots[radix_index(index, height)] = key;
    }

    radix_search成员,原理和radix_insert成员一样,但是不负责分配,只负责查找

    template <typename T, int bits, int height>
    T radix_tree<T, bits, height>::radix_search(int index) {
        pNodetype node = root;
        for (int tree_h = 1; tree_h < height; tree_h++) {
            if (node->autov.DeepNodes == NULL)
                return -1;
            node = &node->autov.DeepNodes[radix_index(index, tree_h)];
        }
        //查询数据
        if (node == root || node->autov.slots == NULL)
            return -1;
        return node->autov.slots[radix_index(index, height)];
    }

    radix_delete成员,采用惰性删除,仅将找到的节点数据变为-1,不删除节点,因为实际应用中,每个数据都是指针,指向对应对象,所以不存在负数

    template <typename T, int bits, int height>
    void radix_tree<T, bits, height>::radix_delete(int index) {
        if (radix_search(index))
            radix_insert(index, -1);
    }

    radix_empty成员,删除所有节点以及数据

    template <typename T, int bits, int height>
    void radix_tree<T, bits, height>::radix_empty() {
        //建议用线程池分配所有,这样方便释放
    //这里未实现,思路是利用线程池,用来分配节点。这样释放时,整体释放线程池;否则比如18位的索引,必须得搜索0x0-0xffff范围的所有索引,然后逐一删除,这样很浪费时间。
    }

    分离定义模版类一定要提前实例化

    template class radix_tree<int, 18, 3>;//index是18位的整数,3是树高

    所有代码均经测试,结果正确。

  • 相关阅读:
    Beta 阶段计划
    alpha阶段总结
    冲刺第十天 12.6 THU
    冲刺第九天 12.5 WED
    冲刺第八天 12.4 TUE
    冲刺第七天 12.3 MON
    冲刺第六天 11.30 FRI
    正弦交流电有效值系数sqrt(2)的推导
    关于STM32官方FOC库函数扇区分析中’131072’系数的解释
    闭环系统零、极点位置对时间响应性能指标的影响
  • 原文地址:https://www.cnblogs.com/dalgleish/p/8983552.html
Copyright © 2011-2022 走看看