zoukankan      html  css  js  c++  java
  • Treap树

    Treap树包含所有二叉树的性质,但是以一个随机的优先值排序。《算法导论》关于这个Treap树的原理和实现描述非常少,我就直接给代码吧,原理大家自己百度了。

    首先定义的个类

    template <typename T>
    class tp_tree {
    public:
        typedef struct _tp_type {
            _tp_type(_tp_type *_p, _tp_type *_left, _tp_type *_right, T _key, int _pr) :
                parent(_p), left(_left), right(_right), key(_key), priority(_pr) {}
            T key;
            int priority;
            _tp_type *left, *right, *parent;
        }tp_type, *ptp_type;
        tp_tree(T *A, int n) :root(NULL) {
            R = hash_mod(n, 3);
            priority_table = new T[R*R];//哈希表
            seed = hash_seed(NULL, R);
            memset(priority_table, 0, sizeof(T)*R*R);
            printf("R=%d, Max slot=%d
    ", R, R*R);
            for (int i = 0; i < n; i++) 
                tp_insert(A[i]);
        }
        ~tp_tree() {
            tp_empty(root);
            hash_seed_free(seed);
            hash_seed_free(priority_table);
        }
        void left_rotate(ptp_type x);
        void right_rotate(ptp_type x);
        void tp_insert(T key);
        ptp_type tp_search(T key);
        void tp_delete(T key);
        void tp_empty(ptp_type x);
        void tp_show(ptp_type x);
        ptp_type tp_root();
    private:
        int hash_mod(int n, int iCheck);//取大小
        int *hash_seed(int *pKey, int R);//获取种子
        void hash_seed_free(int *v);//释放种子
        int hash(int key, int R, int *v);//哈希映射
        void tp_insert_fixup(ptp_type x);
        //测试使用
        int tp_max_depth(ptp_type x);
        int tp_min_depth(ptp_type x);
        ptp_type root;
        int *seed, R;
        T *priority_table;//用于保留T对象,下标是优先值
    };

    关于各个成员实现

    left_roate函数

    template <typename T>
    void tp_tree<T>::left_rotate(typename tp_tree<T>::ptp_type x) {
        ptp_type y = x->right;//y非空
        x->right = y->left;
        if (y->left) y->left->parent = x;//交换子节点
        y->parent = x->parent;//更新父节点
        if (x->parent == NULL)//将y连接到x的父节点
            root = y;
        else {
            if (x == x->parent->left)
                x->parent->left = y;
            else
                x->parent->right = y;
        }
        y->left = x;
        x->parent = y;
    }

    right_rotate函数

    template <typename T>
    void tp_tree<T>::right_rotate(typename tp_tree<T>::ptp_type x) {
        ptp_type y = x->left;
        x->left = y->right;
        if (y->right) y->right->parent = x;
        y->parent = x->parent;
        if (x->parent == NULL)
            root = y;
        else {
            if (x == x->parent->left)
                x->parent->left = y;
            else
                x->parent->right = y;
        }
        y->right = x;
        x->parent = y;
    }

    tp_insert函数

    template <typename T>
    void tp_tree<T>::tp_insert(T key) {
        ptp_type z = NULL, x = root, y = NULL;
        //生成优先值
        int m = hash(key, R, seed);//T类对象,一定要自己实现一个operator int(),使用指针就不需要了
        while (priority_table[m])//循环检查优先表是否被占用
            m = (m + 1) % (R*R);
        priority_table[m] = key;
        z = new tp_type(NULL, NULL, NULL, key, m);
        while (x) {
            y = x;//保留根节点
            if (key < x->key)
                x = x->left;
            else
                x = x->right;
        }
        if (y == NULL)
            root = z;
        else {
            if (key < y->key)
                y->left = z;
            else
                y->right = z;
            z->parent = y;
        }
        tp_insert_fixup(z);
    }

    tp_insert_fixup成员,插入后修复函数

    template <typename T>
    void tp_tree<T>::tp_insert_fixup(typename tp_tree<T>::ptp_type x) {
        ptp_type y;
        while ((y = x->parent) && x->parent->priority > x->priority) {//始终保持父节点的优先值最小
            if (y->right == x)
                left_rotate(y);
            else if (y->left == x)
                right_rotate(y);
        }
    }

    tp_search成员函数

    template <typename T>
    typename tp_tree<T>::ptp_type tp_tree<T>::tp_search(T key) {
        ptp_type x = root;
        while (x != NULL && key != x->key) {
            if (key < x->key)
                x = x->left;
            else
                x = x->right;
        }
        return x;
    }

    tp_delete成员函数,采用堆删除方式,在删除的同时中,就修复了节点

    template <typename T>
    void tp_tree<T>::tp_delete(T key) {
        ptp_type x = tp_search(key), y;
        if (x == NULL) return;
        while (x->left != NULL && x->right != NULL) {//treap堆式删除,将需要的删除的节点通过旋转,移动出来
            if (x->left->priority < x->right->priority)
                right_rotate(x);
            else
                left_rotate(x);
        }
        y = x;//保留待删除节点
        if (x == root)
            root = x->left ? x->left : x->right;
        else if (x->parent->right == x) 
            x->parent->right = x->left ? x->left : x->right;
        else 
            x->parent->left= x->left ? x->left : x->right;
        //清理哈希优先表
        int m = hash(key, R, seed);//T类对象,一定要自己实现一个operator int(),使用指针就不需要了
        while (priority_table[m]) {//循环检查优先表是否被占用
            if (priority_table[m] == key) break;//T类对象还要实现一个operator =(),使用指针就不需要了
            m = (m + 1) % (R*R);
        }
        priority_table[m] = 0;
        //printf("key=%d,hash priority=%d
    ", key, m);
        delete y;
    }

    tp_empty成员函数,删除所有节点

    template <typename T>
    void tp_tree<T>::tp_empty(typename tp_tree<T>::ptp_type x) {
        if (x != NULL) {
            tp_empty(x->left);
            tp_empty(x->right);
            tp_delete(x->key);
        }
    }

    tp_show成员,显示节点,用了AVL树的求深度算法,方便观察并验证算法是否正确

    template <typename T>
    void tp_tree<T>::tp_show(typename tp_tree<T>::ptp_type x) {
        if (x != NULL) {
            tp_show(x->left);
            if (x == root)
                printf("[root]key=%d, priority=%d (%d, %d)
    ", x->key, x->priority, tp_max_depth(x),tp_min_depth(x));
            else
                printf("key=%d, priority=%d (%d, %d)
    ", x->key, x->priority, tp_max_depth(x), tp_min_depth(x));
            tp_show(x->right);
        }
    }
    //测试使用
    template <typename T>
    int tp_tree<T>::tp_max_depth(typename tp_tree<T>::ptp_type x) {
        if (x == NULL)
            return 0;
        int l = tp_max_depth(x->left);
        int r = tp_max_depth(x->right);
        return (l > r ? l : r) + 1;
    }
    
    template <typename T>
    int tp_tree<T>::tp_min_depth(typename tp_tree<T>::ptp_type x) {
        if (x == NULL)
            return 0;
        int l = tp_min_depth(x->left);
        int r = tp_min_depth(x->right);
        return (l < r ? l : r) + 1;
    }

    tp_root成员函数

    template <typename T>
    typename tp_tree<T>::ptp_type tp_tree<T>::tp_root() {
        return root;
    }

    下面几个成员函数,基本来自于之前我写的hash算法那章节,所以没什么好说的

    template <typename T>
    int tp_tree<T>::hash_mod(int n, int iCheck) {
        int iStart = n / iCheck, prime = (iStart == 1) ? 2 : iStart;
        assert(iCheck >= 0 && iCheck <= 8);
        //odd起始要跳过已经判断了的奇数
        for (int j = 0, odd = (iStart % 2 == 0) ? iStart / 2 : (iStart - 1) / 2 + 1;
            j < 8 - iCheck; odd++) {
            //生成一个素数
            bool fPrime = true;
            for (int k = 2; k <= sqrt(prime); k++)
                if (prime % k == 0) {
                    fPrime = false;
                    break;
                }
            if (fPrime) //记录素数
                j++;
            prime = odd * 2 + 1;//待判断的奇数
        }
        return prime - 2;
    }
    
    template <typename T>
    int *tp_tree<T>::hash_seed(int *pKey, int R) {
        int *v = new int[R], key;
        memset(v, 0, R * sizeof(R));
        if (pKey == NULL) {
            srand(time(NULL));
            for (int i = 0; i < R; i++)
                v[i] = rand() % R;
        }
        else {
            key = *pKey;
            for (int i = 0; i < R && key; i++) {
                v[i] = key % R;
                key = key / R;
            }
        }
        return v;
    }
    
    
    template <typename T>
    void tp_tree<T>::hash_seed_free(int *v) {
        delete[] v;
    }
    
    template <typename T>
    int tp_tree<T>::hash(int key, int R, int *v) {
        int slot = 0, M = R*R;
        int *numV = hash_seed(&key, R);
        for (int i = 0; i < R; i++)
            slot += numV[i] * v[i];
        hash_seed_free(numV);
        return slot % M;
    }

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

  • 相关阅读:
    世界编程大赛第一名编写的程序3D世界
    bool与BOOL
    防浪涌电路
    用户至上,体验第一
    VC菜菜鸟创建多线程任务HelloWorld
    Google,a good dog
    算法学习之路
    巧用VC工程下的rc文件
    堆与栈
    关于信息量的压缩
  • 原文地址:https://www.cnblogs.com/dalgleish/p/9071387.html
Copyright © 2011-2022 走看看